]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
pwm: Ensure ioctl() returns a negative errno on error
authorUwe Kleine-König <u.kleine-koenig@baylibre.com>
Mon, 19 Jan 2026 15:13:26 +0000 (16:13 +0100)
committerUwe Kleine-König <ukleinek@kernel.org>
Mon, 19 Jan 2026 16:46:51 +0000 (17:46 +0100)
copy_to_user() returns the number of bytes not copied, thus if there is
a problem a positive number. However the ioctl callback is supposed to
return a negative error code on error.

This error is a unfortunate as strictly speaking it became ABI with the
introduction of pwm character devices. However I never saw the issue in
real life -- I found this by code inspection -- and it only affects an
error case where readonly memory is passed to the ioctls or the address
mapping changes while the ioctl is active. Also there are already error
cases returning negative values, so the calling code must be prepared to
see such values already.

Fixes: 9c06f26ba5f5 ("pwm: Add support for pwmchip devices for faster and easier userspace access")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Link: https://patch.msgid.link/20260119151325.571857-2-u.kleine-koenig@baylibre.com
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
drivers/pwm/core.c

index cd06229db394ed9059599b598ea010c7fe6df137..ec8731515333a0484b0bbdfe6befcd69e82b5fa9 100644 (file)
@@ -2295,8 +2295,9 @@ static long pwm_cdev_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                                .duty_offset_ns = wf.duty_offset_ns,
                        };
 
-                       return copy_to_user((struct pwmchip_waveform __user *)arg,
-                                           &cwf, sizeof(cwf));
+                       ret = copy_to_user((struct pwmchip_waveform __user *)arg,
+                                          &cwf, sizeof(cwf));
+                       return ret ? -EFAULT : 0;
                }
 
        case PWM_IOCTL_GETWF:
@@ -2329,8 +2330,9 @@ static long pwm_cdev_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                                .duty_offset_ns = wf.duty_offset_ns,
                        };
 
-                       return copy_to_user((struct pwmchip_waveform __user *)arg,
-                                           &cwf, sizeof(cwf));
+                       ret = copy_to_user((struct pwmchip_waveform __user *)arg,
+                                          &cwf, sizeof(cwf));
+                       return ret ? -EFAULT : 0;
                }
 
        case PWM_IOCTL_SETROUNDEDWF: