From 076ff658628678f73d2349a699c3431877c1a075 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 24 Aug 2018 00:11:19 +0200 Subject: compat_ioctl: move rtc handling into drivers/rtc/dev.c We no longer need the rtc compat handling to be in common code, now that all drivers are either moved to the rtc-class framework, or (rarely) exist in drivers/char for architectures without compat mode (m68k, alpha and ia64, respectively). I checked the list of ioctl commands in drivers, and the ones that are not already handled are all compatible, again with the one exception of m68k driver, which implements RTC_PLL_GET and RTC_PLL_SET, but has no compat mode. Unlike earlier versions of this patch, I'm now adding a separate compat_ioctl handler that takes care of RTC_IRQP_READ32/RTC_IRQP_SET32 and treats all other commands as compatible, leaving the native behavior unchanged. The old conversion handler also deals with RTC_EPOCH_READ and RTC_EPOCH_SET, which are not handled in rtc-dev.c but only in a single device driver (rtc-vr41xx), so I'm adding the compat version in the same place. I don't expect other drivers to need those commands in the future. Acked-by: Alexandre Belloni Reviewed-by: Ben Hutchings Signed-off-by: Arnd Bergmann --- v4: handle RTC_EPOCH_SET32 in rtc_dev_compat_ioctl v3: handle RTC_IRQP_READ32/RTC_IRQP_SET32 in rtc_dev_compat_ioctl v2: merge compat handler into ioctl function to avoid the compat_alloc_user_space() roundtrip, based on feedback from Al Viro. --- drivers/rtc/dev.c | 33 ++++++++++++++++++++++++++++++++- drivers/rtc/rtc-vr41xx.c | 8 ++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c index 84feb2565abd..5b8ebe86124a 100644 --- a/drivers/rtc/dev.c +++ b/drivers/rtc/dev.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -360,7 +361,6 @@ static long rtc_dev_ioctl(struct file *file, case RTC_IRQP_SET: err = rtc_irq_set_freq(rtc, arg); break; - case RTC_IRQP_READ: err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); break; @@ -399,6 +399,34 @@ done: return err; } +#ifdef CONFIG_COMPAT +#define RTC_IRQP_SET32 _IOW('p', 0x0c, __u32) +#define RTC_IRQP_READ32 _IOR('p', 0x0b, __u32) +#define RTC_EPOCH_SET32 _IOW('p', 0x0e, __u32) + +static long rtc_dev_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct rtc_device *rtc = file->private_data; + void __user *uarg = compat_ptr(arg); + + switch (cmd) { + case RTC_IRQP_READ32: + return put_user(rtc->irq_freq, (__u32 __user *)uarg); + + case RTC_IRQP_SET32: + /* arg is a plain integer, not pointer */ + return rtc_dev_ioctl(file, RTC_IRQP_SET, arg); + + case RTC_EPOCH_SET32: + /* arg is a plain integer, not pointer */ + return rtc_dev_ioctl(file, RTC_EPOCH_SET, arg); + } + + return rtc_dev_ioctl(file, cmd, (unsigned long)uarg); +} +#endif + static int rtc_dev_fasync(int fd, struct file *file, int on) { struct rtc_device *rtc = file->private_data; @@ -434,6 +462,9 @@ static const struct file_operations rtc_dev_fops = { .read = rtc_dev_read, .poll = rtc_dev_poll, .unlocked_ioctl = rtc_dev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = rtc_dev_compat_ioctl, +#endif .open = rtc_dev_open, .release = rtc_dev_release, .fasync = rtc_dev_fasync, diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index c75230562c0d..c3671043ace7 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -4,6 +4,7 @@ * * Copyright (C) 2003-2008 Yoichi Yuasa */ +#include #include #include #include @@ -66,6 +67,9 @@ static void __iomem *rtc2_base; #define rtc2_read(offset) readw(rtc2_base + (offset)) #define rtc2_write(offset, value) writew((value), rtc2_base + (offset)) +/* 32-bit compat for ioctls that nobody else uses */ +#define RTC_EPOCH_READ32 _IOR('p', 0x0d, __u32) + static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ static DEFINE_SPINLOCK(rtc_lock); @@ -179,6 +183,10 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long switch (cmd) { case RTC_EPOCH_READ: return put_user(epoch, (unsigned long __user *)arg); +#ifdef CONFIG_64BIT + case RTC_EPOCH_READ32: + return put_user(epoch, (unsigned int __user *)arg); +#endif case RTC_EPOCH_SET: /* Doesn't support before 1900 */ if (arg < 1900) -- cgit v1.2.3-59-g8ed1b From 407e9ef72476e64937ebec44cc835e03a25fb408 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 11 Sep 2018 17:23:00 +0200 Subject: compat_ioctl: move drivers to compat_ptr_ioctl Each of these drivers has a copy of the same trivial helper function to convert the pointer argument and then call the native ioctl handler. We now have a generic implementation of that, so use it. Acked-by: Greg Kroah-Hartman Acked-by: Michael S. Tsirkin Acked-by: David S. Miller Acked-by: Jarkko Sakkinen Reviewed-by: Jarkko Sakkinen Reviewed-by: Jason Gunthorpe Reviewed-by: Jiri Kosina Reviewed-by: Stefan Hajnoczi Reviewed-by: Cornelia Huck Signed-off-by: Arnd Bergmann --- drivers/char/ppdev.c | 12 +----------- drivers/char/tpm/tpm_vtpm_proxy.c | 12 +----------- drivers/firewire/core-cdev.c | 12 +----------- drivers/hid/usbhid/hiddev.c | 11 +---------- drivers/hwtracing/stm/core.c | 12 +----------- drivers/misc/mei/main.c | 22 +--------------------- drivers/mtd/ubi/cdev.c | 36 +++--------------------------------- drivers/net/tap.c | 12 +----------- drivers/staging/pi433/pi433_if.c | 12 +----------- drivers/usb/core/devio.c | 16 +--------------- drivers/vfio/vfio.c | 39 +++------------------------------------ drivers/vhost/net.c | 12 +----------- drivers/vhost/scsi.c | 12 +----------- drivers/vhost/test.c | 12 +----------- drivers/vhost/vsock.c | 12 +----------- fs/fat/file.c | 13 +------------ 16 files changed, 20 insertions(+), 237 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index c86f18aa8985..e02fe2621b94 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -670,14 +670,6 @@ static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } -#ifdef CONFIG_COMPAT -static long pp_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return pp_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - static int pp_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); @@ -786,9 +778,7 @@ static const struct file_operations pp_fops = { .write = pp_write, .poll = pp_poll, .unlocked_ioctl = pp_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = pp_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = pp_open, .release = pp_release, }; diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index 2f6e087ec496..91c772e38bb5 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -670,20 +670,10 @@ static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl, } } -#ifdef CONFIG_COMPAT -static long vtpmx_fops_compat_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) -{ - return vtpmx_fops_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); -} -#endif - static const struct file_operations vtpmx_fops = { .owner = THIS_MODULE, .unlocked_ioctl = vtpmx_fops_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vtpmx_fops_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 1da7ba18d399..c777088f5828 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1646,14 +1646,6 @@ static long fw_device_op_ioctl(struct file *file, return dispatch_ioctl(file->private_data, cmd, (void __user *)arg); } -#ifdef CONFIG_COMPAT -static long fw_device_op_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return dispatch_ioctl(file->private_data, cmd, compat_ptr(arg)); -} -#endif - static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) { struct client *client = file->private_data; @@ -1795,7 +1787,5 @@ const struct file_operations fw_device_ops = { .mmap = fw_device_op_mmap, .release = fw_device_op_release, .poll = fw_device_op_poll, -#ifdef CONFIG_COMPAT - .compat_ioctl = fw_device_op_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, }; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 1f9bc4483465..e421cdf2d1a4 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -854,13 +854,6 @@ ret_unlock: return r; } -#ifdef CONFIG_COMPAT -static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return hiddev_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - static const struct file_operations hiddev_fops = { .owner = THIS_MODULE, .read = hiddev_read, @@ -870,9 +863,7 @@ static const struct file_operations hiddev_fops = { .release = hiddev_release, .unlocked_ioctl = hiddev_ioctl, .fasync = hiddev_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = hiddev_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index 603b83ac5085..2712e699ba08 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -832,23 +832,13 @@ stm_char_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; } -#ifdef CONFIG_COMPAT -static long -stm_char_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return stm_char_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); -} -#else -#define stm_char_compat_ioctl NULL -#endif - static const struct file_operations stm_fops = { .open = stm_char_open, .release = stm_char_release, .write = stm_char_write, .mmap = stm_char_mmap, .unlocked_ioctl = stm_char_ioctl, - .compat_ioctl = stm_char_compat_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = no_llseek, }; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 7310b476323c..133fa8cbb1c8 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -532,24 +532,6 @@ out: return rets; } -/** - * mei_compat_ioctl - the compat IOCTL function - * - * @file: pointer to file structure - * @cmd: ioctl command - * @data: pointer to mei message structure - * - * Return: 0 on success , <0 on error - */ -#ifdef CONFIG_COMPAT -static long mei_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long data) -{ - return mei_ioctl(file, cmd, (unsigned long)compat_ptr(data)); -} -#endif - - /** * mei_poll - the poll function * @@ -898,9 +880,7 @@ static const struct file_operations mei_fops = { .owner = THIS_MODULE, .read = mei_read, .unlocked_ioctl = mei_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = mei_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = mei_open, .release = mei_release, .write = mei_write, diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 1b77fff9f892..cc9a28cf9d82 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -1078,36 +1078,6 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd, return err; } -#ifdef CONFIG_COMPAT -static long vol_cdev_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - unsigned long translated_arg = (unsigned long)compat_ptr(arg); - - return vol_cdev_ioctl(file, cmd, translated_arg); -} - -static long ubi_cdev_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - unsigned long translated_arg = (unsigned long)compat_ptr(arg); - - return ubi_cdev_ioctl(file, cmd, translated_arg); -} - -static long ctrl_cdev_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - unsigned long translated_arg = (unsigned long)compat_ptr(arg); - - return ctrl_cdev_ioctl(file, cmd, translated_arg); -} -#else -#define vol_cdev_compat_ioctl NULL -#define ubi_cdev_compat_ioctl NULL -#define ctrl_cdev_compat_ioctl NULL -#endif - /* UBI volume character device operations */ const struct file_operations ubi_vol_cdev_operations = { .owner = THIS_MODULE, @@ -1118,7 +1088,7 @@ const struct file_operations ubi_vol_cdev_operations = { .write = vol_cdev_write, .fsync = vol_cdev_fsync, .unlocked_ioctl = vol_cdev_ioctl, - .compat_ioctl = vol_cdev_compat_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; /* UBI character device operations */ @@ -1126,13 +1096,13 @@ const struct file_operations ubi_cdev_operations = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = ubi_cdev_ioctl, - .compat_ioctl = ubi_cdev_compat_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; /* UBI control character device operations */ const struct file_operations ubi_ctrl_cdev_operations = { .owner = THIS_MODULE, .unlocked_ioctl = ctrl_cdev_ioctl, - .compat_ioctl = ctrl_cdev_compat_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = no_llseek, }; diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 3ae70c7e6860..a6d63665ad03 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -1123,14 +1123,6 @@ static long tap_ioctl(struct file *file, unsigned int cmd, } } -#ifdef CONFIG_COMPAT -static long tap_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return tap_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - static const struct file_operations tap_fops = { .owner = THIS_MODULE, .open = tap_open, @@ -1140,9 +1132,7 @@ static const struct file_operations tap_fops = { .poll = tap_poll, .llseek = no_llseek, .unlocked_ioctl = tap_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = tap_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, }; static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 40c6f4e7632f..313d22f6210f 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -928,16 +928,6 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return 0; } -#ifdef CONFIG_COMPAT -static long -pi433_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - return pi433_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); -} -#else -#define pi433_compat_ioctl NULL -#endif /* CONFIG_COMPAT */ - /*-------------------------------------------------------------------------*/ static int pi433_open(struct inode *inode, struct file *filp) @@ -1094,7 +1084,7 @@ static const struct file_operations pi433_fops = { .write = pi433_write, .read = pi433_read, .unlocked_ioctl = pi433_ioctl, - .compat_ioctl = pi433_compat_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pi433_open, .release = pi433_release, .llseek = no_llseek, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 3f899552f6e3..646ffa13c1fc 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2685,18 +2685,6 @@ static long usbdev_ioctl(struct file *file, unsigned int cmd, return ret; } -#ifdef CONFIG_COMPAT -static long usbdev_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int ret; - - ret = usbdev_do_ioctl(file, cmd, compat_ptr(arg)); - - return ret; -} -#endif - /* No kernel lock - fine */ static __poll_t usbdev_poll(struct file *file, struct poll_table_struct *wait) @@ -2720,9 +2708,7 @@ const struct file_operations usbdev_file_operations = { .read = usbdev_read, .poll = usbdev_poll, .unlocked_ioctl = usbdev_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = usbdev_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .mmap = usbdev_mmap, .open = usbdev_open, .release = usbdev_release, diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 388597930b64..c8482624ca34 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1184,15 +1184,6 @@ static long vfio_fops_unl_ioctl(struct file *filep, return ret; } -#ifdef CONFIG_COMPAT -static long vfio_fops_compat_ioctl(struct file *filep, - unsigned int cmd, unsigned long arg) -{ - arg = (unsigned long)compat_ptr(arg); - return vfio_fops_unl_ioctl(filep, cmd, arg); -} -#endif /* CONFIG_COMPAT */ - static int vfio_fops_open(struct inode *inode, struct file *filep) { struct vfio_container *container; @@ -1275,9 +1266,7 @@ static const struct file_operations vfio_fops = { .read = vfio_fops_read, .write = vfio_fops_write, .unlocked_ioctl = vfio_fops_unl_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vfio_fops_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .mmap = vfio_fops_mmap, }; @@ -1556,15 +1545,6 @@ static long vfio_group_fops_unl_ioctl(struct file *filep, return ret; } -#ifdef CONFIG_COMPAT -static long vfio_group_fops_compat_ioctl(struct file *filep, - unsigned int cmd, unsigned long arg) -{ - arg = (unsigned long)compat_ptr(arg); - return vfio_group_fops_unl_ioctl(filep, cmd, arg); -} -#endif /* CONFIG_COMPAT */ - static int vfio_group_fops_open(struct inode *inode, struct file *filep) { struct vfio_group *group; @@ -1620,9 +1600,7 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep) static const struct file_operations vfio_group_fops = { .owner = THIS_MODULE, .unlocked_ioctl = vfio_group_fops_unl_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vfio_group_fops_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = vfio_group_fops_open, .release = vfio_group_fops_release, }; @@ -1687,24 +1665,13 @@ static int vfio_device_fops_mmap(struct file *filep, struct vm_area_struct *vma) return device->ops->mmap(device->device_data, vma); } -#ifdef CONFIG_COMPAT -static long vfio_device_fops_compat_ioctl(struct file *filep, - unsigned int cmd, unsigned long arg) -{ - arg = (unsigned long)compat_ptr(arg); - return vfio_device_fops_unl_ioctl(filep, cmd, arg); -} -#endif /* CONFIG_COMPAT */ - static const struct file_operations vfio_device_fops = { .owner = THIS_MODULE, .release = vfio_device_fops_release, .read = vfio_device_fops_read, .write = vfio_device_fops_write, .unlocked_ioctl = vfio_device_fops_unl_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vfio_device_fops_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .mmap = vfio_device_fops_mmap, }; diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 1a2dd53caade..e158159671fa 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1751,14 +1751,6 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl, } } -#ifdef CONFIG_COMPAT -static long vhost_net_compat_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) -{ - return vhost_net_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); -} -#endif - static ssize_t vhost_net_chr_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct file *file = iocb->ki_filp; @@ -1794,9 +1786,7 @@ static const struct file_operations vhost_net_fops = { .write_iter = vhost_net_chr_write_iter, .poll = vhost_net_chr_poll, .unlocked_ioctl = vhost_net_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vhost_net_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = vhost_net_open, .llseek = noop_llseek, }; diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index a9caf1bc3c3e..0b949a14bce3 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1727,21 +1727,11 @@ vhost_scsi_ioctl(struct file *f, } } -#ifdef CONFIG_COMPAT -static long vhost_scsi_compat_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) -{ - return vhost_scsi_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); -} -#endif - static const struct file_operations vhost_scsi_fops = { .owner = THIS_MODULE, .release = vhost_scsi_release, .unlocked_ioctl = vhost_scsi_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vhost_scsi_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = vhost_scsi_open, .llseek = noop_llseek, }; diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 7804869c6a31..ec58a3330e5e 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -302,21 +302,11 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl, } } -#ifdef CONFIG_COMPAT -static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) -{ - return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); -} -#endif - static const struct file_operations vhost_test_fops = { .owner = THIS_MODULE, .release = vhost_test_release, .unlocked_ioctl = vhost_test_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vhost_test_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = vhost_test_open, .llseek = noop_llseek, }; diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 9f57736fe15e..706c5e8e01ee 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -761,23 +761,13 @@ static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl, } } -#ifdef CONFIG_COMPAT -static long vhost_vsock_dev_compat_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) -{ - return vhost_vsock_dev_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); -} -#endif - static const struct file_operations vhost_vsock_fops = { .owner = THIS_MODULE, .open = vhost_vsock_dev_open, .release = vhost_vsock_dev_release, .llseek = noop_llseek, .unlocked_ioctl = vhost_vsock_dev_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = vhost_vsock_dev_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice vhost_vsock_misc = { diff --git a/fs/fat/file.c b/fs/fat/file.c index 4614c0ba5f1c..bdc4503c00a3 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -172,15 +172,6 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } -#ifdef CONFIG_COMPAT -static long fat_generic_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) - -{ - return fat_generic_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - static int fat_file_release(struct inode *inode, struct file *filp) { if ((filp->f_mode & FMODE_WRITE) && @@ -215,9 +206,7 @@ const struct file_operations fat_file_operations = { .mmap = generic_file_mmap, .release = fat_file_release, .unlocked_ioctl = fat_generic_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = fat_generic_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .fsync = fat_file_fsync, .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, -- cgit v1.2.3-59-g8ed1b From 1832f2d8ff69138aa70d3cb3b4ea3c2058e73aea Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 11 Sep 2018 21:59:08 +0200 Subject: compat_ioctl: move more drivers to compat_ptr_ioctl The .ioctl and .compat_ioctl file operations have the same prototype so they can both point to the same function, which works great almost all the time when all the commands are compatible. One exception is the s390 architecture, where a compat pointer is only 31 bit wide, and converting it into a 64-bit pointer requires calling compat_ptr(). Most drivers here will never run in s390, but since we now have a generic helper for it, it's easy enough to use it consistently. I double-checked all these drivers to ensure that all ioctl arguments are used as pointers or are ignored, but are not interpreted as integer values. Acked-by: Jason Gunthorpe Acked-by: Daniel Vetter Acked-by: Mauro Carvalho Chehab Acked-by: Greg Kroah-Hartman Acked-by: David Sterba Acked-by: Darren Hart (VMware) Acked-by: Jonathan Cameron Acked-by: Bjorn Andersson Acked-by: Dan Williams Signed-off-by: Arnd Bergmann --- drivers/android/binder.c | 2 +- drivers/crypto/qat/qat_common/adf_ctl_drv.c | 2 +- drivers/dma-buf/dma-buf.c | 4 +--- drivers/dma-buf/sw_sync.c | 2 +- drivers/dma-buf/sync_file.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/hid/hidraw.c | 4 +--- drivers/iio/industrialio-core.c | 2 +- drivers/infiniband/core/uverbs_main.c | 4 ++-- drivers/media/rc/lirc_dev.c | 4 +--- drivers/misc/vmw_vmci/vmci_host.c | 2 +- drivers/nvdimm/bus.c | 4 ++-- drivers/nvme/host/core.c | 2 +- drivers/pci/switch/switchtec.c | 2 +- drivers/platform/x86/wmi.c | 2 +- drivers/rpmsg/rpmsg_char.c | 4 ++-- drivers/sbus/char/display7seg.c | 2 +- drivers/sbus/char/envctrl.c | 4 +--- drivers/scsi/3w-xxxx.c | 4 +--- drivers/scsi/cxlflash/main.c | 2 +- drivers/scsi/esas2r/esas2r_main.c | 2 +- drivers/scsi/pmcraid.c | 4 +--- drivers/staging/android/ion/ion.c | 4 +--- drivers/staging/vme/devices/vme_user.c | 2 +- drivers/tee/tee_core.c | 2 +- drivers/usb/class/cdc-wdm.c | 2 +- drivers/usb/class/usbtmc.c | 4 +--- drivers/virt/fsl_hypervisor.c | 2 +- fs/btrfs/super.c | 2 +- fs/fuse/dev.c | 2 +- fs/notify/fanotify/fanotify_user.c | 2 +- fs/userfaultfd.c | 2 +- net/rfkill/core.c | 2 +- 33 files changed, 36 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/android/binder.c b/drivers/android/binder.c index c0a491277aca..c7079f071e23 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -6063,7 +6063,7 @@ const struct file_operations binder_fops = { .owner = THIS_MODULE, .poll = binder_poll, .unlocked_ioctl = binder_ioctl, - .compat_ioctl = binder_ioctl, + .compat_ioctl = compat_ptr_ioctl, .mmap = binder_mmap, .open = binder_open, .flush = binder_flush, diff --git a/drivers/crypto/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/qat/qat_common/adf_ctl_drv.c index abc7a7f64d64..ef0e482ee04f 100644 --- a/drivers/crypto/qat/qat_common/adf_ctl_drv.c +++ b/drivers/crypto/qat/qat_common/adf_ctl_drv.c @@ -68,7 +68,7 @@ static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); static const struct file_operations adf_ctl_ops = { .owner = THIS_MODULE, .unlocked_ioctl = adf_ctl_ioctl, - .compat_ioctl = adf_ctl_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; struct adf_ctl_drv_info { diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 433d91d710e4..5b8797be80df 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -415,9 +415,7 @@ static const struct file_operations dma_buf_fops = { .llseek = dma_buf_llseek, .poll = dma_buf_poll, .unlocked_ioctl = dma_buf_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = dma_buf_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .show_fdinfo = dma_buf_show_fdinfo, }; diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 6713cfb1995c..348b3a9170fa 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -408,5 +408,5 @@ const struct file_operations sw_sync_debugfs_fops = { .open = sw_sync_debugfs_open, .release = sw_sync_debugfs_release, .unlocked_ioctl = sw_sync_ioctl, - .compat_ioctl = sw_sync_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 25c5c071645b..76fb072c22dc 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -480,5 +480,5 @@ static const struct file_operations sync_file_fops = { .release = sync_file_release, .poll = sync_file_poll, .unlocked_ioctl = sync_file_ioctl, - .compat_ioctl = sync_file_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 1d3cd5c50d5f..6283944387d6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -49,7 +49,7 @@ static const char kfd_dev_name[] = "kfd"; static const struct file_operations kfd_fops = { .owner = THIS_MODULE, .unlocked_ioctl = kfd_ioctl, - .compat_ioctl = kfd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = kfd_open, .mmap = kfd_mmap, }; diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index bbc6ec1aa5cb..a925f9fa7011 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -468,9 +468,7 @@ static const struct file_operations hidraw_ops = { .release = hidraw_release, .unlocked_ioctl = hidraw_ioctl, .fasync = hidraw_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = hidraw_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 524a686077ca..9dd687534035 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1610,7 +1610,7 @@ static const struct file_operations iio_buffer_fileops = { .owner = THIS_MODULE, .llseek = noop_llseek, .unlocked_ioctl = iio_ioctl, - .compat_ioctl = iio_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static int iio_check_unique_scan_index(struct iio_dev *indio_dev) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index db98111b47f4..c4c652e87044 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -1139,7 +1139,7 @@ static const struct file_operations uverbs_fops = { .release = ib_uverbs_close, .llseek = no_llseek, .unlocked_ioctl = ib_uverbs_ioctl, - .compat_ioctl = ib_uverbs_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static const struct file_operations uverbs_mmap_fops = { @@ -1150,7 +1150,7 @@ static const struct file_operations uverbs_mmap_fops = { .release = ib_uverbs_close, .llseek = no_llseek, .unlocked_ioctl = ib_uverbs_ioctl, - .compat_ioctl = ib_uverbs_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static int ib_uverbs_get_nl_info(struct ib_device *ibdev, void *client_data, diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index f078f8a3aec8..9a8c1cf54ac4 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -720,9 +720,7 @@ static const struct file_operations lirc_fops = { .owner = THIS_MODULE, .write = ir_lirc_transmit_ir, .unlocked_ioctl = ir_lirc_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ir_lirc_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .read = ir_lirc_read, .poll = ir_lirc_poll, .open = ir_lirc_open, diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index 833e2bd248a5..903e321e8e87 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -961,7 +961,7 @@ static const struct file_operations vmuser_fops = { .release = vmci_host_close, .poll = vmci_host_poll, .unlocked_ioctl = vmci_host_unlocked_ioctl, - .compat_ioctl = vmci_host_unlocked_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice vmci_host_miscdev = { diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index d47412dcdf38..38d41bbf178a 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -1227,7 +1227,7 @@ static const struct file_operations nvdimm_bus_fops = { .owner = THIS_MODULE, .open = nd_open, .unlocked_ioctl = bus_ioctl, - .compat_ioctl = bus_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; @@ -1235,7 +1235,7 @@ static const struct file_operations nvdimm_fops = { .owner = THIS_MODULE, .open = nd_open, .unlocked_ioctl = dimm_ioctl, - .compat_ioctl = dimm_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index fd7dea36c3b6..522280eb4115 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2947,7 +2947,7 @@ static const struct file_operations nvme_dev_fops = { .owner = THIS_MODULE, .open = nvme_dev_open, .unlocked_ioctl = nvme_dev_ioctl, - .compat_ioctl = nvme_dev_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static ssize_t nvme_sysfs_reset(struct device *dev, diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c index 8c94cd3fd1f2..66610f04d76d 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -1025,7 +1025,7 @@ static const struct file_operations switchtec_fops = { .read = switchtec_dev_read, .poll = switchtec_dev_poll, .unlocked_ioctl = switchtec_dev_ioctl, - .compat_ioctl = switchtec_dev_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static void link_event_work(struct work_struct *work) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 59e9aa0f9643..dc2e966a5c25 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -911,7 +911,7 @@ static const struct file_operations wmi_fops = { .read = wmi_char_read, .open = wmi_char_open, .unlocked_ioctl = wmi_ioctl, - .compat_ioctl = wmi_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static int wmi_dev_probe(struct device *dev) diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index eea5ebbb5119..507bfe163883 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -290,7 +290,7 @@ static const struct file_operations rpmsg_eptdev_fops = { .write_iter = rpmsg_eptdev_write_iter, .poll = rpmsg_eptdev_poll, .unlocked_ioctl = rpmsg_eptdev_ioctl, - .compat_ioctl = rpmsg_eptdev_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static ssize_t name_show(struct device *dev, struct device_attribute *attr, @@ -451,7 +451,7 @@ static const struct file_operations rpmsg_ctrldev_fops = { .open = rpmsg_ctrldev_open, .release = rpmsg_ctrldev_release, .unlocked_ioctl = rpmsg_ctrldev_ioctl, - .compat_ioctl = rpmsg_ctrldev_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static void rpmsg_ctrldev_release_device(struct device *dev) diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 971fe074d7c9..fad936eb845f 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -156,7 +156,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static const struct file_operations d7s_fops = { .owner = THIS_MODULE, .unlocked_ioctl = d7s_ioctl, - .compat_ioctl = d7s_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = d7s_open, .release = d7s_release, .llseek = noop_llseek, diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index a63d5e402ff2..12d66aa61ede 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -715,9 +715,7 @@ static const struct file_operations envctrl_fops = { .owner = THIS_MODULE, .read = envctrl_read, .unlocked_ioctl = envctrl_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = envctrl_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = envctrl_open, .release = envctrl_release, .llseek = noop_llseek, diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 2b1e0d503020..fb6444d0409c 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1049,9 +1049,7 @@ static int tw_chrdev_open(struct inode *inode, struct file *file) static const struct file_operations tw_fops = { .owner = THIS_MODULE, .unlocked_ioctl = tw_chrdev_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = tw_chrdev_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .open = tw_chrdev_open, .release = NULL, .llseek = noop_llseek, diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 93ef97af22df..2dbf35f82787 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -3593,7 +3593,7 @@ static const struct file_operations cxlflash_chr_fops = { .owner = THIS_MODULE, .open = cxlflash_chr_open, .unlocked_ioctl = cxlflash_chr_ioctl, - .compat_ioctl = cxlflash_chr_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; /** diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index fdbda5c05aa0..80c5a235d193 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -613,7 +613,7 @@ static int __init esas2r_init(void) /* Handle ioctl calls to "/proc/scsi/esas2r/ATTOnode" */ static const struct file_operations esas2r_proc_fops = { - .compat_ioctl = esas2r_proc_ioctl, + .compat_ioctl = compat_ptr_ioctl, .unlocked_ioctl = esas2r_proc_ioctl, }; diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 398d2af60832..7eb88fe1eb0b 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3973,9 +3973,7 @@ static const struct file_operations pmcraid_fops = { .open = pmcraid_chr_open, .fasync = pmcraid_chr_fasync, .unlocked_ioctl = pmcraid_chr_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = pmcraid_chr_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e6b1ca141b93..c394686a8e7d 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -533,9 +533,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) static const struct file_operations ion_fops = { .owner = THIS_MODULE, .unlocked_ioctl = ion_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ion_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, }; static int debug_shrink_set(void *data, u64 val) diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index 6a33aaa1a49f..fd0ea4dbcb91 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -494,7 +494,7 @@ static const struct file_operations vme_user_fops = { .write = vme_user_write, .llseek = vme_user_llseek, .unlocked_ioctl = vme_user_unlocked_ioctl, - .compat_ioctl = vme_user_unlocked_ioctl, + .compat_ioctl = compat_ptr_ioctl, .mmap = vme_user_mmap, }; diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 0f16d9ffd8d1..37d22e39fd8d 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -675,7 +675,7 @@ static const struct file_operations tee_fops = { .open = tee_open, .release = tee_release, .unlocked_ioctl = tee_ioctl, - .compat_ioctl = tee_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static void tee_release_device(struct device *dev) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 70afb2ca1eab..e3db6fbeadef 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -734,7 +734,7 @@ static const struct file_operations wdm_fops = { .release = wdm_release, .poll = wdm_poll, .unlocked_ioctl = wdm_ioctl, - .compat_ioctl = wdm_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index dcd7066ffba2..ffc9c6fdd7e1 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2217,9 +2217,7 @@ static const struct file_operations fops = { .release = usbtmc_release, .flush = usbtmc_flush, .unlocked_ioctl = usbtmc_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = usbtmc_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .fasync = usbtmc_fasync, .poll = usbtmc_poll, .llseek = default_llseek, diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c index 93d5bebf9572..1b0b11b55d2a 100644 --- a/drivers/virt/fsl_hypervisor.c +++ b/drivers/virt/fsl_hypervisor.c @@ -706,7 +706,7 @@ static const struct file_operations fsl_hv_fops = { .poll = fsl_hv_poll, .read = fsl_hv_read, .unlocked_ioctl = fsl_hv_ioctl, - .compat_ioctl = fsl_hv_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice fsl_hv_misc_dev = { diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 1b151af25772..d9ba089a4973 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2297,7 +2297,7 @@ static const struct super_operations btrfs_super_ops = { static const struct file_operations btrfs_ctl_fops = { .open = btrfs_control_open, .unlocked_ioctl = btrfs_control_ioctl, - .compat_ioctl = btrfs_control_ioctl, + .compat_ioctl = compat_ptr_ioctl, .owner = THIS_MODULE, .llseek = noop_llseek, }; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index dadd617d826c..23b089e6880a 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2260,7 +2260,7 @@ const struct file_operations fuse_dev_operations = { .release = fuse_dev_release, .fasync = fuse_dev_fasync, .unlocked_ioctl = fuse_dev_ioctl, - .compat_ioctl = fuse_dev_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; EXPORT_SYMBOL_GPL(fuse_dev_operations); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 8508ab575017..0aa362b88550 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -523,7 +523,7 @@ static const struct file_operations fanotify_fops = { .fasync = NULL, .release = fanotify_release, .unlocked_ioctl = fanotify_ioctl, - .compat_ioctl = fanotify_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index f9fd18670e22..d7f54e535294 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1923,7 +1923,7 @@ static const struct file_operations userfaultfd_fops = { .poll = userfaultfd_poll, .read = userfaultfd_read, .unlocked_ioctl = userfaultfd_ioctl, - .compat_ioctl = userfaultfd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; diff --git a/net/rfkill/core.c b/net/rfkill/core.c index f9b08a6d8dbe..c4be6a94ba97 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -1311,7 +1311,7 @@ static const struct file_operations rfkill_fops = { .release = rfkill_fop_release, #ifdef CONFIG_RFKILL_INPUT .unlocked_ioctl = rfkill_fop_ioctl, - .compat_ioctl = rfkill_fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, #endif .llseek = no_llseek, }; -- cgit v1.2.3-59-g8ed1b From 01b8bca81e181ccca475e1fdb92ebb00d9d9b547 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 11 Sep 2018 17:28:08 +0200 Subject: compat_ioctl: use correct compat_ptr() translation in drivers A handful of drivers all have a trivial wrapper around their ioctl handler, but don't call the compat_ptr() conversion function at the moment. In practice this does not matter, since none of them are used on the s390 architecture and for all other architectures, compat_ptr() does not do anything, but using the new compat_ptr_ioctl() helper makes it more correct in theory, and simplifies the code. I checked that all ioctl handlers in these files are compatible and take either pointer arguments or no argument. Acked-by: Al Viro Acked-by: Greg Kroah-Hartman Acked-by: Andrew Donnellan Acked-by: Felipe Balbi Signed-off-by: Arnd Bergmann --- drivers/misc/cxl/flash.c | 8 +------- drivers/misc/genwqe/card_dev.c | 23 +---------------------- drivers/scsi/megaraid/megaraid_mm.c | 28 +--------------------------- drivers/usb/gadget/function/f_fs.c | 12 +----------- 4 files changed, 4 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/cxl/flash.c b/drivers/misc/cxl/flash.c index 4d6836f19489..cb9cca35a226 100644 --- a/drivers/misc/cxl/flash.c +++ b/drivers/misc/cxl/flash.c @@ -473,12 +473,6 @@ static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; } -static long device_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return device_ioctl(file, cmd, arg); -} - static int device_close(struct inode *inode, struct file *file) { struct cxl *adapter = file->private_data; @@ -514,7 +508,7 @@ static const struct file_operations fops = { .owner = THIS_MODULE, .open = device_open, .unlocked_ioctl = device_ioctl, - .compat_ioctl = device_compat_ioctl, + .compat_ioctl = compat_ptr_ioctl, .release = device_close, }; diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index 0e34c0568fed..040a0bda3125 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -1215,34 +1215,13 @@ static long genwqe_ioctl(struct file *filp, unsigned int cmd, return rc; } -#if defined(CONFIG_COMPAT) -/** - * genwqe_compat_ioctl() - Compatibility ioctl - * - * Called whenever a 32-bit process running under a 64-bit kernel - * performs an ioctl on /dev/genwqe_card. - * - * @filp: file pointer. - * @cmd: command. - * @arg: user argument. - * Return: zero on success or negative number on failure. - */ -static long genwqe_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - return genwqe_ioctl(filp, cmd, arg); -} -#endif /* defined(CONFIG_COMPAT) */ - static const struct file_operations genwqe_fops = { .owner = THIS_MODULE, .open = genwqe_open, .fasync = genwqe_fasync, .mmap = genwqe_mmap, .unlocked_ioctl = genwqe_ioctl, -#if defined(CONFIG_COMPAT) - .compat_ioctl = genwqe_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .release = genwqe_release, }; diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 59cca898f088..e83163c66884 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -41,10 +41,6 @@ static int mraid_mm_setup_dma_pools(mraid_mmadp_t *); static void mraid_mm_free_adp_resources(mraid_mmadp_t *); static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *); -#ifdef CONFIG_COMPAT -static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long); -#endif - MODULE_AUTHOR("LSI Logic Corporation"); MODULE_DESCRIPTION("LSI Logic Management Module"); MODULE_LICENSE("GPL"); @@ -68,9 +64,7 @@ static wait_queue_head_t wait_q; static const struct file_operations lsi_fops = { .open = mraid_mm_open, .unlocked_ioctl = mraid_mm_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = mraid_mm_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, .owner = THIS_MODULE, .llseek = noop_llseek, }; @@ -224,7 +218,6 @@ mraid_mm_unlocked_ioctl(struct file *filep, unsigned int cmd, { int err; - /* inconsistent: mraid_mm_compat_ioctl doesn't take the BKL */ mutex_lock(&mraid_mm_mutex); err = mraid_mm_ioctl(filep, cmd, arg); mutex_unlock(&mraid_mm_mutex); @@ -1228,25 +1221,6 @@ mraid_mm_init(void) } -#ifdef CONFIG_COMPAT -/** - * mraid_mm_compat_ioctl - 32bit to 64bit ioctl conversion routine - * @filep : file operations pointer (ignored) - * @cmd : ioctl command - * @arg : user ioctl packet - */ -static long -mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd, - unsigned long arg) -{ - int err; - - err = mraid_mm_ioctl(filep, cmd, arg); - - return err; -} -#endif - /** * mraid_mm_exit - Module exit point */ diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 59d9d512dcda..ce1d0235969c 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1352,14 +1352,6 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, return ret; } -#ifdef CONFIG_COMPAT -static long ffs_epfile_compat_ioctl(struct file *file, unsigned code, - unsigned long value) -{ - return ffs_epfile_ioctl(file, code, value); -} -#endif - static const struct file_operations ffs_epfile_operations = { .llseek = no_llseek, @@ -1368,9 +1360,7 @@ static const struct file_operations ffs_epfile_operations = { .read_iter = ffs_epfile_read_iter, .release = ffs_epfile_release, .unlocked_ioctl = ffs_epfile_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ffs_epfile_compat_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, }; -- cgit v1.2.3-59-g8ed1b From 1207045da5a7c94344e0ea9a9e7495985eef499a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 7 Sep 2018 16:49:43 +0200 Subject: compat_ioctl: move tape handling into drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MTIOCPOS and MTIOCGET are incompatible between 32-bit and 64-bit user space, and traditionally have been translated in fs/compat_ioctl.c. To get rid of that translation handler, move a corresponding implementation into each of the four drivers implementing those commands. The interesting part of that is now in a new linux/mtio.h header that wraps the existing uapi/linux/mtio.h header and provides an abstraction to let drivers handle both cases easily. Using an in_compat_syscall() check, the caller does not have to keep track of whether this was called through .unlocked_ioctl() or .compat_ioctl(). Acked-by: Heiko Carstens Cc: "Kai Mäkisara" Cc: linux-scsi@vger.kernel.org Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: "David S. Miller" Signed-off-by: Arnd Bergmann --- drivers/ide/ide-tape.c | 27 ++++++++++++---- drivers/s390/char/tape_char.c | 41 +++++++++--------------- drivers/scsi/st.c | 28 +++++++++++------ fs/compat_ioctl.c | 73 ------------------------------------------- include/linux/mtio.h | 60 +++++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 115 deletions(-) create mode 100644 include/linux/mtio.h (limited to 'drivers') diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index db1a65f4b490..3e7482695f77 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -19,6 +19,7 @@ #define IDETAPE_VERSION "1.20" +#include #include #include #include @@ -1407,14 +1408,10 @@ static long do_idetape_chrdev_ioctl(struct file *file, if (tape->drv_write_prot) mtget.mt_gstat |= GMT_WR_PROT(0xffffffff); - if (copy_to_user(argp, &mtget, sizeof(struct mtget))) - return -EFAULT; - return 0; + return put_user_mtget(argp, &mtget); case MTIOCPOS: mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; - if (copy_to_user(argp, &mtpos, sizeof(struct mtpos))) - return -EFAULT; - return 0; + return put_user_mtpos(argp, &mtpos); default: if (tape->chrdev_dir == IDETAPE_DIR_READ) ide_tape_discard_merge_buffer(drive, 1); @@ -1432,6 +1429,22 @@ static long idetape_chrdev_ioctl(struct file *file, return ret; } +static long idetape_chrdev_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + long ret; + + if (cmd == MTIOCPOS32) + cmd = MTIOCPOS; + else if (cmd == MTIOCGET32) + cmd = MTIOCGET; + + mutex_lock(&ide_tape_mutex); + ret = do_idetape_chrdev_ioctl(file, cmd, arg); + mutex_unlock(&ide_tape_mutex); + return ret; +} + /* * Do a mode sense page 0 with block descriptor and if it succeeds set the tape * block size with the reported value. @@ -1886,6 +1899,8 @@ static const struct file_operations idetape_fops = { .read = idetape_chrdev_read, .write = idetape_chrdev_write, .unlocked_ioctl = idetape_chrdev_ioctl, + .compat_ioctl = IS_ENABLED(CONFIG_COMPAT) ? + idetape_chrdev_compat_ioctl : NULL, .open = idetape_chrdev_open, .release = idetape_chrdev_release, .llseek = noop_llseek, diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index ea4253939555..8abb42923307 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -341,14 +341,14 @@ tapechar_release(struct inode *inode, struct file *filp) */ static int __tapechar_ioctl(struct tape_device *device, - unsigned int no, unsigned long data) + unsigned int no, void __user *data) { int rc; if (no == MTIOCTOP) { struct mtop op; - if (copy_from_user(&op, (char __user *) data, sizeof(op)) != 0) + if (copy_from_user(&op, data, sizeof(op)) != 0) return -EFAULT; if (op.mt_count < 0) return -EINVAL; @@ -392,9 +392,7 @@ __tapechar_ioctl(struct tape_device *device, if (rc < 0) return rc; pos.mt_blkno = rc; - if (copy_to_user((char __user *) data, &pos, sizeof(pos)) != 0) - return -EFAULT; - return 0; + return put_user_mtpos(data, &pos); } if (no == MTIOCGET) { /* MTIOCGET: query the tape drive status. */ @@ -424,15 +422,12 @@ __tapechar_ioctl(struct tape_device *device, get.mt_blkno = rc; } - if (copy_to_user((char __user *) data, &get, sizeof(get)) != 0) - return -EFAULT; - - return 0; + return put_user_mtget(data, &get); } /* Try the discipline ioctl function. */ if (device->discipline->ioctl_fn == NULL) return -EINVAL; - return device->discipline->ioctl_fn(device, no, data); + return device->discipline->ioctl_fn(device, no, (unsigned long)data); } static long @@ -445,7 +440,7 @@ tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data) device = (struct tape_device *) filp->private_data; mutex_lock(&device->mutex); - rc = __tapechar_ioctl(device, no, data); + rc = __tapechar_ioctl(device, no, (void __user *)data); mutex_unlock(&device->mutex); return rc; } @@ -455,23 +450,17 @@ static long tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) { struct tape_device *device = filp->private_data; - int rval = -ENOIOCTLCMD; - unsigned long argp; + long rc; - /* The 'arg' argument of any ioctl function may only be used for - * pointers because of the compat pointer conversion. - * Consider this when adding new ioctls. - */ - argp = (unsigned long) compat_ptr(data); - if (device->discipline->ioctl_fn) { - mutex_lock(&device->mutex); - rval = device->discipline->ioctl_fn(device, no, argp); - mutex_unlock(&device->mutex); - if (rval == -EINVAL) - rval = -ENOIOCTLCMD; - } + if (no == MTIOCPOS32) + no = MTIOCPOS; + else if (no == MTIOCGET32) + no = MTIOCGET; - return rval; + mutex_lock(&device->mutex); + rc = __tapechar_ioctl(device, no, compat_ptr(data)); + mutex_unlock(&device->mutex); + return rc; } #endif /* CONFIG_COMPAT */ diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index e3266a64a477..9e3fff2de83e 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -22,6 +22,7 @@ static const char *verstr = "20160209"; #include +#include #include #include #include @@ -3800,14 +3801,11 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) if (STp->cleaning_req) mt_status.mt_gstat |= GMT_CLN(0xffffffff); - i = copy_to_user(p, &mt_status, sizeof(struct mtget)); - if (i) { - retval = (-EFAULT); + retval = put_user_mtget(p, &mt_status); + if (retval) goto out; - } STp->recover_reg = 0; /* Clear after read */ - retval = 0; goto out; } /* End of MTIOCGET */ if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) { @@ -3821,9 +3819,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) goto out; } mt_pos.mt_blkno = blk; - i = copy_to_user(p, &mt_pos, sizeof(struct mtpos)); - if (i) - retval = (-EFAULT); + retval = put_user_mtpos(p, &mt_pos); goto out; } mutex_unlock(&STp->lock); @@ -3857,14 +3853,26 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) } #ifdef CONFIG_COMPAT -static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) { + void __user *p = compat_ptr(arg); struct scsi_tape *STp = file->private_data; struct scsi_device *sdev = STp->device; int ret = -ENOIOCTLCMD; + + /* argument conversion is handled using put_user_mtpos/put_user_mtget */ + switch (cmd_in) { + case MTIOCTOP: + return st_ioctl(file, MTIOCTOP, (unsigned long)p); + case MTIOCPOS32: + return st_ioctl(file, MTIOCPOS, (unsigned long)p); + case MTIOCGET32: + return st_ioctl(file, MTIOCGET, (unsigned long)p); + } + if (sdev->host->hostt->compat_ioctl) { - ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); } return ret; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 47da220f95b1..b65eef3d4787 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -361,73 +360,6 @@ static int ppp_scompress(struct file *file, unsigned int cmd, return do_ioctl(file, PPPIOCSCOMPRESS, (unsigned long) odata); } -#ifdef CONFIG_BLOCK -struct mtget32 { - compat_long_t mt_type; - compat_long_t mt_resid; - compat_long_t mt_dsreg; - compat_long_t mt_gstat; - compat_long_t mt_erreg; - compat_daddr_t mt_fileno; - compat_daddr_t mt_blkno; -}; -#define MTIOCGET32 _IOR('m', 2, struct mtget32) - -struct mtpos32 { - compat_long_t mt_blkno; -}; -#define MTIOCPOS32 _IOR('m', 3, struct mtpos32) - -static int mt_ioctl_trans(struct file *file, - unsigned int cmd, void __user *argp) -{ - /* NULL initialization to make gcc shut up */ - struct mtget __user *get = NULL; - struct mtget32 __user *umget32; - struct mtpos __user *pos = NULL; - struct mtpos32 __user *upos32; - unsigned long kcmd; - void *karg; - int err = 0; - - switch(cmd) { - case MTIOCPOS32: - kcmd = MTIOCPOS; - pos = compat_alloc_user_space(sizeof(*pos)); - karg = pos; - break; - default: /* MTIOCGET32 */ - kcmd = MTIOCGET; - get = compat_alloc_user_space(sizeof(*get)); - karg = get; - break; - } - if (karg == NULL) - return -EFAULT; - err = do_ioctl(file, kcmd, (unsigned long)karg); - if (err) - return err; - switch (cmd) { - case MTIOCPOS32: - upos32 = argp; - err = convert_in_user(&pos->mt_blkno, &upos32->mt_blkno); - break; - case MTIOCGET32: - umget32 = argp; - err = convert_in_user(&get->mt_type, &umget32->mt_type); - err |= convert_in_user(&get->mt_resid, &umget32->mt_resid); - err |= convert_in_user(&get->mt_dsreg, &umget32->mt_dsreg); - err |= convert_in_user(&get->mt_gstat, &umget32->mt_gstat); - err |= convert_in_user(&get->mt_erreg, &umget32->mt_erreg); - err |= convert_in_user(&get->mt_fileno, &umget32->mt_fileno); - err |= convert_in_user(&get->mt_blkno, &umget32->mt_blkno); - break; - } - return err ? -EFAULT: 0; -} - -#endif /* CONFIG_BLOCK */ - /* Bluetooth ioctls */ #define HCIUARTSETPROTO _IOW('U', 200, int) #define HCIUARTGETPROTO _IOR('U', 201, int) @@ -479,8 +411,6 @@ IGNORE_IOCTL(VT_GETMODE) */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -/* Little m */ -COMPATIBLE_IOCTL(MTIOCTOP) #ifdef CONFIG_BLOCK /* md calls this on random blockdevs */ IGNORE_IOCTL(RAID_VERSION) @@ -846,9 +776,6 @@ static long do_ioctl_trans(unsigned int cmd, return sg_ioctl_trans(file, cmd, argp); case SG_GET_REQUEST_TABLE: return sg_grt_trans(file, cmd, argp); - case MTIOCGET32: - case MTIOCPOS32: - return mt_ioctl_trans(file, cmd, argp); #endif } diff --git a/include/linux/mtio.h b/include/linux/mtio.h new file mode 100644 index 000000000000..67d03156f2c2 --- /dev/null +++ b/include/linux/mtio.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_MTIO_COMPAT_H +#define _LINUX_MTIO_COMPAT_H + +#include +#include +#include + +/* + * helper functions for implementing compat ioctls on the four tape + * drivers: we define the 32-bit layout of each incompatible structure, + * plus a wrapper function to copy it to user space in either format. + */ + +struct mtget32 { + s32 mt_type; + s32 mt_resid; + s32 mt_dsreg; + s32 mt_gstat; + s32 mt_erreg; + s32 mt_fileno; + s32 mt_blkno; +}; +#define MTIOCGET32 _IOR('m', 2, struct mtget32) + +struct mtpos32 { + s32 mt_blkno; +}; +#define MTIOCPOS32 _IOR('m', 3, struct mtpos32) + +static inline int put_user_mtget(void __user *u, struct mtget *k) +{ + struct mtget32 k32 = { + .mt_type = k->mt_type, + .mt_resid = k->mt_resid, + .mt_dsreg = k->mt_dsreg, + .mt_gstat = k->mt_gstat, + .mt_erreg = k->mt_erreg, + .mt_fileno = k->mt_fileno, + .mt_blkno = k->mt_blkno, + }; + int ret; + + if (in_compat_syscall()) + ret = copy_to_user(u, &k32, sizeof(k32)); + else + ret = copy_to_user(u, k, sizeof(*k)); + + return ret ? -EFAULT : 0; +} + +static inline int put_user_mtpos(void __user *u, struct mtpos *k) +{ + if (in_compat_syscall()) + return put_user(k->mt_blkno, (u32 __user *)u); + else + return put_user(k->mt_blkno, (long __user *)u); +} + +#endif -- cgit v1.2.3-59-g8ed1b From 0ba9841adb8659856cebb3b54a555e45a5f7fce5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 14 Mar 2019 12:14:17 +0100 Subject: compat_ioctl: move ATYFB_CLK handling to atyfb driver These are two obscure ioctl commands, in a driver that only has compatible commands, so just let the driver handle this itself. Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Arnd Bergmann --- drivers/video/fbdev/aty/atyfb_base.c | 12 +++++++++++- fs/compat_ioctl.c | 2 -- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index 6dda5d885a03..79d548746efd 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -48,7 +48,7 @@ ******************************************************************************/ - +#include #include #include #include @@ -235,6 +235,13 @@ static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int atyfb_blank(int blank, struct fb_info *info); static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); +#ifdef CONFIG_COMPAT +static int atyfb_compat_ioctl(struct fb_info *info, u_int cmd, u_long arg) +{ + return atyfb_ioctl(info, cmd, (u_long)compat_ptr(arg)); +} +#endif + #ifdef __sparc__ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma); #endif @@ -290,6 +297,9 @@ static struct fb_ops atyfb_ops = { .fb_pan_display = atyfb_pan_display, .fb_blank = atyfb_blank, .fb_ioctl = atyfb_ioctl, +#ifdef CONFIG_COMPAT + .fb_compat_ioctl = atyfb_compat_ioctl, +#endif .fb_fillrect = atyfb_fillrect, .fb_copyarea = atyfb_copyarea, .fb_imageblit = atyfb_imageblit, diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index b65eef3d4787..a4e8fb7da968 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -696,8 +696,6 @@ COMPATIBLE_IOCTL(CAPI_CLR_FLAGS) COMPATIBLE_IOCTL(CAPI_NCCI_OPENCOUNT) COMPATIBLE_IOCTL(CAPI_NCCI_GETUNIT) /* Misc. */ -COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ -COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) -- cgit v1.2.3-59-g8ed1b From 5565a3cac5038561155e57451604fce2b5eb4dd7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 6 Sep 2018 23:17:20 +0200 Subject: compat_ioctl: move isdn/capi ioctl translation into driver Neither the old isdn4linux interface nor the newer mISDN stack ever had working 32-bit compat mode as far as I can tell. However, the CAPI stack has some ioctl commands that are correctly listed in fs/compat_ioctl.c. We can trivially move all of those into the corresponding file that implement the native handlers by adding a compat_ioctl redirect to that. I did notice that treating CAPI_MANUFACTURER_CMD() as compatible is broken, so I'm also adding a handler for that, realizing that in all likelyhood, nobody is ever going to call it. Cc: Karsten Keil Cc: netdev@vger.kernel.org Cc: isdn4linux@listserv.isdn4linux.de Signed-off-by: Arnd Bergmann --- drivers/isdn/capi/capi.c | 31 +++++++++++++++++++++++++++++++ fs/compat_ioctl.c | 17 ----------------- 2 files changed, 31 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index c92b405b7646..6fbe3949026c 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -950,6 +950,34 @@ capi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } +#ifdef CONFIG_COMPAT +static long +capi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret; + + if (cmd == CAPI_MANUFACTURER_CMD) { + struct { + compat_ulong_t cmd; + compat_uptr_t data; + } mcmd32; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user(&mcmd32, compat_ptr(arg), sizeof(mcmd32))) + return -EFAULT; + + mutex_lock(&capi_mutex); + ret = capi20_manufacturer(mcmd32.cmd, compat_ptr(mcmd32.data)); + mutex_unlock(&capi_mutex); + + return ret; + } + + return capi_unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + static int capi_open(struct inode *inode, struct file *file) { struct capidev *cdev; @@ -996,6 +1024,9 @@ static const struct file_operations capi_fops = .write = capi_write, .poll = capi_poll, .unlocked_ioctl = capi_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = capi_compat_ioctl, +#endif .open = capi_open, .release = capi_release, }; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index a4e8fb7da968..f3b4179d6dff 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -44,9 +44,6 @@ #include #include -#include -#include - #ifdef CONFIG_BLOCK #include #include @@ -681,20 +678,6 @@ COMPATIBLE_IOCTL(RFCOMMRELEASEDEV) COMPATIBLE_IOCTL(RFCOMMGETDEVLIST) COMPATIBLE_IOCTL(RFCOMMGETDEVINFO) COMPATIBLE_IOCTL(RFCOMMSTEALDLC) -/* CAPI */ -COMPATIBLE_IOCTL(CAPI_REGISTER) -COMPATIBLE_IOCTL(CAPI_GET_MANUFACTURER) -COMPATIBLE_IOCTL(CAPI_GET_VERSION) -COMPATIBLE_IOCTL(CAPI_GET_SERIAL) -COMPATIBLE_IOCTL(CAPI_GET_PROFILE) -COMPATIBLE_IOCTL(CAPI_MANUFACTURER_CMD) -COMPATIBLE_IOCTL(CAPI_GET_ERRCODE) -COMPATIBLE_IOCTL(CAPI_INSTALLED) -COMPATIBLE_IOCTL(CAPI_GET_FLAGS) -COMPATIBLE_IOCTL(CAPI_SET_FLAGS) -COMPATIBLE_IOCTL(CAPI_CLR_FLAGS) -COMPATIBLE_IOCTL(CAPI_NCCI_OPENCOUNT) -COMPATIBLE_IOCTL(CAPI_NCCI_GETUNIT) /* Misc. */ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) -- cgit v1.2.3-59-g8ed1b From 507e4e2b430b6a27b66f4745564ecaee7967737f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 7 Sep 2018 11:10:23 +0200 Subject: compat_ioctl: remove /dev/random commands These are all handled by the random driver, so instead of listing each ioctl, we can use the generic compat_ptr_ioctl() helper. Acked-by: Greg Kroah-Hartman Signed-off-by: Arnd Bergmann --- drivers/char/random.c | 1 + fs/compat_ioctl.c | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/char/random.c b/drivers/char/random.c index de434feb873a..46afd14facb7 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -2167,6 +2167,7 @@ const struct file_operations random_fops = { .write = random_write, .poll = random_poll, .unlocked_ioctl = random_ioctl, + .compat_ioctl = compat_ptr_ioctl, .fasync = random_fasync, .llseek = noop_llseek, }; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 10dfe4d80bbd..398268604ab7 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -439,13 +439,6 @@ COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT) COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT) COMPATIBLE_IOCTL(WDIOC_SETPRETIMEOUT) COMPATIBLE_IOCTL(WDIOC_GETPRETIMEOUT) -/* Big R */ -COMPATIBLE_IOCTL(RNDGETENTCNT) -COMPATIBLE_IOCTL(RNDADDTOENTCNT) -COMPATIBLE_IOCTL(RNDGETPOOL) -COMPATIBLE_IOCTL(RNDADDENTROPY) -COMPATIBLE_IOCTL(RNDZAPENTCNT) -COMPATIBLE_IOCTL(RNDCLEARPOOL) /* Misc. */ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) -- cgit v1.2.3-59-g8ed1b From b6dfb2477fb0bf48e31999d306d2552144891f6e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jun 2019 14:23:09 +0200 Subject: compat_ioctl: move WDIOC handling into wdt drivers All watchdog drivers implement the same set of ioctl commands, and fortunately all of them are compatible between 32-bit and 64-bit architectures. Modern drivers always go through drivers/watchdog/wdt.c as an abstraction layer, but older ones implement their own file_operations on a character device for this. Move the handling from fs/compat_ioctl.c into the individual drivers. Note that most of the legacy drivers will never be used on 64-bit hardware, because they are for an old 32-bit SoC implementation, but doing them all at once is safer than trying to guess which ones do or do not need the compat_ioctl handling. Reviewed-by: Guenter Roeck Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/52xx/mpc52xx_gpt.c | 1 + arch/um/drivers/harddog_kern.c | 1 + drivers/char/ipmi/ipmi_watchdog.c | 1 + drivers/hwmon/fschmd.c | 1 + drivers/hwmon/w83793.c | 1 + drivers/rtc/rtc-ds1374.c | 1 + drivers/rtc/rtc-m41t80.c | 1 + drivers/watchdog/acquirewdt.c | 1 + drivers/watchdog/advantechwdt.c | 1 + drivers/watchdog/alim1535_wdt.c | 1 + drivers/watchdog/alim7101_wdt.c | 1 + drivers/watchdog/ar7_wdt.c | 1 + drivers/watchdog/at91rm9200_wdt.c | 1 + drivers/watchdog/ath79_wdt.c | 1 + drivers/watchdog/bcm63xx_wdt.c | 1 + drivers/watchdog/cpu5wdt.c | 1 + drivers/watchdog/eurotechwdt.c | 1 + drivers/watchdog/f71808e_wdt.c | 1 + drivers/watchdog/gef_wdt.c | 1 + drivers/watchdog/geodewdt.c | 1 + drivers/watchdog/ib700wdt.c | 1 + drivers/watchdog/ibmasr.c | 1 + drivers/watchdog/indydog.c | 1 + drivers/watchdog/intel_scu_watchdog.c | 1 + drivers/watchdog/iop_wdt.c | 1 + drivers/watchdog/it8712f_wdt.c | 1 + drivers/watchdog/ixp4xx_wdt.c | 1 + drivers/watchdog/m54xx_wdt.c | 1 + drivers/watchdog/machzwd.c | 1 + drivers/watchdog/mixcomwd.c | 1 + drivers/watchdog/mtx-1_wdt.c | 1 + drivers/watchdog/mv64x60_wdt.c | 1 + drivers/watchdog/nv_tco.c | 1 + drivers/watchdog/pc87413_wdt.c | 1 + drivers/watchdog/pcwd.c | 1 + drivers/watchdog/pcwd_pci.c | 1 + drivers/watchdog/pcwd_usb.c | 1 + drivers/watchdog/pika_wdt.c | 1 + drivers/watchdog/pnx833x_wdt.c | 1 + drivers/watchdog/rc32434_wdt.c | 1 + drivers/watchdog/rdc321x_wdt.c | 1 + drivers/watchdog/riowd.c | 1 + drivers/watchdog/sa1100_wdt.c | 1 + drivers/watchdog/sb_wdog.c | 1 + drivers/watchdog/sbc60xxwdt.c | 1 + drivers/watchdog/sbc7240_wdt.c | 1 + drivers/watchdog/sbc_epx_c3.c | 1 + drivers/watchdog/sbc_fitpc2_wdt.c | 1 + drivers/watchdog/sc1200wdt.c | 1 + drivers/watchdog/sc520_wdt.c | 1 + drivers/watchdog/sch311x_wdt.c | 1 + drivers/watchdog/scx200_wdt.c | 1 + drivers/watchdog/smsc37b787_wdt.c | 1 + drivers/watchdog/w83877f_wdt.c | 1 + drivers/watchdog/w83977f_wdt.c | 1 + drivers/watchdog/wafer5823wdt.c | 1 + drivers/watchdog/watchdog_dev.c | 1 + drivers/watchdog/wdrtas.c | 1 + drivers/watchdog/wdt.c | 1 + drivers/watchdog/wdt285.c | 1 + drivers/watchdog/wdt977.c | 1 + drivers/watchdog/wdt_pci.c | 1 + fs/compat_ioctl.c | 11 ----------- 63 files changed, 62 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index ba12dc14a3d1..8c0d324f657e 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -650,6 +650,7 @@ static const struct file_operations mpc52xx_wdt_fops = { .llseek = no_llseek, .write = mpc52xx_wdt_write, .unlocked_ioctl = mpc52xx_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mpc52xx_wdt_open, .release = mpc52xx_wdt_release, }; diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 000cb69ba0bc..e6d4f43deba8 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -165,6 +165,7 @@ static const struct file_operations harddog_fops = { .owner = THIS_MODULE, .write = harddog_write, .unlocked_ioctl = harddog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = harddog_open, .release = harddog_release, .llseek = no_llseek, diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 74c6d1f34132..55986e10a124 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -893,6 +893,7 @@ static const struct file_operations ipmi_wdog_fops = { .poll = ipmi_poll, .write = ipmi_write, .unlocked_ioctl = ipmi_unlocked_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ipmi_open, .release = ipmi_close, .fasync = ipmi_fasync, diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index fa0c2f1fb443..4136643d8e0c 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -954,6 +954,7 @@ static const struct file_operations watchdog_fops = { .release = watchdog_release, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 9df48b70c70c..55c5f86125e3 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -1458,6 +1458,7 @@ static const struct file_operations watchdog_fops = { .release = watchdog_close, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; /* diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 367497914c10..6e96916c41ff 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -586,6 +586,7 @@ static const struct file_operations ds1374_wdt_fops = { .owner = THIS_MODULE, .read = ds1374_wdt_read, .unlocked_ioctl = ds1374_wdt_unlocked_ioctl, + .compat_ioctl = compat_ptr_ioctl, .write = ds1374_wdt_write, .open = ds1374_wdt_open, .release = ds1374_wdt_release, diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 5f46f85f814b..f9fa4f068de3 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -840,6 +840,7 @@ static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .read = wdt_read, .unlocked_ioctl = wdt_unlocked_ioctl, + .compat_ioctl = compat_ptr_ioctl, .write = wdt_write, .open = wdt_open, .release = wdt_release, diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 848db958411e..bc6f333565d3 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -221,6 +221,7 @@ static const struct file_operations acq_fops = { .llseek = no_llseek, .write = acq_write, .unlocked_ioctl = acq_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = acq_open, .release = acq_close, }; diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index 0d02bb275b3d..0e4c18a2aa42 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c @@ -220,6 +220,7 @@ static const struct file_operations advwdt_fops = { .llseek = no_llseek, .write = advwdt_write, .unlocked_ioctl = advwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = advwdt_open, .release = advwdt_close, }; diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index c157dd3d92a3..42338c7d4540 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c @@ -362,6 +362,7 @@ static const struct file_operations ali_fops = { .llseek = no_llseek, .write = ali_write, .unlocked_ioctl = ali_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ali_open, .release = ali_release, }; diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index c8e3ab056767..5af0358f4390 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c @@ -294,6 +294,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index 668a1c704f28..c087027ffd5d 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c @@ -250,6 +250,7 @@ static const struct file_operations ar7_wdt_fops = { .owner = THIS_MODULE, .write = ar7_wdt_write, .unlocked_ioctl = ar7_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ar7_wdt_open, .release = ar7_wdt_release, .llseek = no_llseek, diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index 907a4545dee6..6d751eb8191d 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -213,6 +213,7 @@ static const struct file_operations at91wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = at91_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = at91_wdt_open, .release = at91_wdt_close, .write = at91_wdt_write, diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c index 75de664ef4b0..d6dff97c280b 100644 --- a/drivers/watchdog/ath79_wdt.c +++ b/drivers/watchdog/ath79_wdt.c @@ -234,6 +234,7 @@ static const struct file_operations ath79_wdt_fops = { .llseek = no_llseek, .write = ath79_wdt_write, .unlocked_ioctl = ath79_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ath79_wdt_open, .release = ath79_wdt_release, }; diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index e2af37c9a266..8a043b52aa2f 100644 --- a/drivers/watchdog/bcm63xx_wdt.c +++ b/drivers/watchdog/bcm63xx_wdt.c @@ -221,6 +221,7 @@ static const struct file_operations bcm63xx_wdt_fops = { .llseek = no_llseek, .write = bcm63xx_wdt_write, .unlocked_ioctl = bcm63xx_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = bcm63xx_wdt_open, .release = bcm63xx_wdt_release, }; diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c index d6d53014cb68..9867a3a936df 100644 --- a/drivers/watchdog/cpu5wdt.c +++ b/drivers/watchdog/cpu5wdt.c @@ -187,6 +187,7 @@ static const struct file_operations cpu5wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = cpu5wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = cpu5wdt_open, .write = cpu5wdt_write, .release = cpu5wdt_release, diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 3a83a48abcae..f5ffa7be066e 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -371,6 +371,7 @@ static const struct file_operations eurwdt_fops = { .llseek = no_llseek, .write = eurwdt_write, .unlocked_ioctl = eurwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = eurwdt_open, .release = eurwdt_release, }; diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index e46104c2fd94..a3c44d75d80e 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -669,6 +669,7 @@ static const struct file_operations watchdog_fops = { .release = watchdog_release, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice watchdog_miscdev = { diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 7d5f56994f09..f6541d1b65e3 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -248,6 +248,7 @@ static const struct file_operations gef_wdt_fops = { .llseek = no_llseek, .write = gef_wdt_write, .unlocked_ioctl = gef_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = gef_wdt_open, .release = gef_wdt_release, }; diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 8d105d98908e..9914a4283cb2 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c @@ -201,6 +201,7 @@ static const struct file_operations geodewdt_fops = { .llseek = no_llseek, .write = geodewdt_write, .unlocked_ioctl = geodewdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = geodewdt_open, .release = geodewdt_release, }; diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c index 92fd7f33bc4d..2b65ea9451d1 100644 --- a/drivers/watchdog/ib700wdt.c +++ b/drivers/watchdog/ib700wdt.c @@ -259,6 +259,7 @@ static const struct file_operations ibwdt_fops = { .llseek = no_llseek, .write = ibwdt_write, .unlocked_ioctl = ibwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ibwdt_open, .release = ibwdt_close, }; diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c index 897f7eda9e6a..4a22fe152086 100644 --- a/drivers/watchdog/ibmasr.c +++ b/drivers/watchdog/ibmasr.c @@ -344,6 +344,7 @@ static const struct file_operations asr_fops = { .llseek = no_llseek, .write = asr_write, .unlocked_ioctl = asr_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = asr_open, .release = asr_release, }; diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c index 550358528084..9857bb74a723 100644 --- a/drivers/watchdog/indydog.c +++ b/drivers/watchdog/indydog.c @@ -152,6 +152,7 @@ static const struct file_operations indydog_fops = { .llseek = no_llseek, .write = indydog_write, .unlocked_ioctl = indydog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = indydog_open, .release = indydog_release, }; diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c index 1c85103b750b..6ad5bf3451ec 100644 --- a/drivers/watchdog/intel_scu_watchdog.c +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -412,6 +412,7 @@ static const struct file_operations intel_scu_fops = { .llseek = no_llseek, .write = intel_scu_write, .unlocked_ioctl = intel_scu_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = intel_scu_open, .release = intel_scu_release, }; diff --git a/drivers/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c index a9ccdb9a9159..6bf68d4750de 100644 --- a/drivers/watchdog/iop_wdt.c +++ b/drivers/watchdog/iop_wdt.c @@ -202,6 +202,7 @@ static const struct file_operations iop_wdt_fops = { .llseek = no_llseek, .write = iop_wdt_write, .unlocked_ioctl = iop_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = iop_wdt_open, .release = iop_wdt_release, }; diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index 2fe1a3c499ed..2fed40d14007 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c @@ -345,6 +345,7 @@ static const struct file_operations it8712f_wdt_fops = { .llseek = no_llseek, .write = it8712f_wdt_write, .unlocked_ioctl = it8712f_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = it8712f_wdt_open, .release = it8712f_wdt_release, }; diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c index 9067998759e3..09886616fd21 100644 --- a/drivers/watchdog/ixp4xx_wdt.c +++ b/drivers/watchdog/ixp4xx_wdt.c @@ -163,6 +163,7 @@ static const struct file_operations ixp4xx_wdt_fops = { .llseek = no_llseek, .write = ixp4xx_wdt_write, .unlocked_ioctl = ixp4xx_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = ixp4xx_wdt_open, .release = ixp4xx_wdt_release, }; diff --git a/drivers/watchdog/m54xx_wdt.c b/drivers/watchdog/m54xx_wdt.c index 752d03620f0a..22f335e1e164 100644 --- a/drivers/watchdog/m54xx_wdt.c +++ b/drivers/watchdog/m54xx_wdt.c @@ -183,6 +183,7 @@ static const struct file_operations m54xx_wdt_fops = { .llseek = no_llseek, .write = m54xx_wdt_write, .unlocked_ioctl = m54xx_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = m54xx_wdt_open, .release = m54xx_wdt_release, }; diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index cef2baf59dda..80ff94688487 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c @@ -361,6 +361,7 @@ static const struct file_operations zf_fops = { .llseek = no_llseek, .write = zf_write, .unlocked_ioctl = zf_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = zf_open, .release = zf_close, }; diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c index a86faa5000f1..d387bad377c4 100644 --- a/drivers/watchdog/mixcomwd.c +++ b/drivers/watchdog/mixcomwd.c @@ -227,6 +227,7 @@ static const struct file_operations mixcomwd_fops = { .llseek = no_llseek, .write = mixcomwd_write, .unlocked_ioctl = mixcomwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mixcomwd_open, .release = mixcomwd_release, }; diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 25a92857b217..8aa1cb4a295f 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -181,6 +181,7 @@ static const struct file_operations mtx1_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = mtx1_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mtx1_wdt_open, .write = mtx1_wdt_write, .release = mtx1_wdt_release, diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index 74bf7144a970..0bc72dd69b70 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c @@ -241,6 +241,7 @@ static const struct file_operations mv64x60_wdt_fops = { .llseek = no_llseek, .write = mv64x60_wdt_write, .unlocked_ioctl = mv64x60_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mv64x60_wdt_open, .release = mv64x60_wdt_release, }; diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c index 5f0082e300bd..d7a560e348d5 100644 --- a/drivers/watchdog/nv_tco.c +++ b/drivers/watchdog/nv_tco.c @@ -267,6 +267,7 @@ static const struct file_operations nv_tco_fops = { .llseek = no_llseek, .write = nv_tco_write, .unlocked_ioctl = nv_tco_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = nv_tco_open, .release = nv_tco_release, }; diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 2af1a8b3f973..73fbfc99083b 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -473,6 +473,7 @@ static const struct file_operations pc87413_fops = { .llseek = no_llseek, .write = pc87413_write, .unlocked_ioctl = pc87413_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pc87413_open, .release = pc87413_release, }; diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index c3c93e00b320..7a0587fdc52c 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c @@ -752,6 +752,7 @@ static const struct file_operations pcwd_fops = { .llseek = no_llseek, .write = pcwd_write, .unlocked_ioctl = pcwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pcwd_open, .release = pcwd_close, }; diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index e30c1f762045..81508a42a90c 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c @@ -646,6 +646,7 @@ static const struct file_operations pcipcwd_fops = { .llseek = no_llseek, .write = pcipcwd_write, .unlocked_ioctl = pcipcwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pcipcwd_open, .release = pcipcwd_release, }; diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 6727f8ab2d18..2f44af1831d0 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -550,6 +550,7 @@ static const struct file_operations usb_pcwd_fops = { .llseek = no_llseek, .write = usb_pcwd_write, .unlocked_ioctl = usb_pcwd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = usb_pcwd_open, .release = usb_pcwd_release, }; diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c index 205c3c68fca1..a98abd0d3146 100644 --- a/drivers/watchdog/pika_wdt.c +++ b/drivers/watchdog/pika_wdt.c @@ -214,6 +214,7 @@ static const struct file_operations pikawdt_fops = { .release = pikawdt_release, .write = pikawdt_write, .unlocked_ioctl = pikawdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice pikawdt_miscdev = { diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c index aa53babf2bab..4097d076aab8 100644 --- a/drivers/watchdog/pnx833x_wdt.c +++ b/drivers/watchdog/pnx833x_wdt.c @@ -215,6 +215,7 @@ static const struct file_operations pnx833x_wdt_fops = { .llseek = no_llseek, .write = pnx833x_wdt_write, .unlocked_ioctl = pnx833x_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = pnx833x_wdt_open, .release = pnx833x_wdt_release, }; diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index a8a4b3a41a90..1dfede0abf18 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -245,6 +245,7 @@ static const struct file_operations rc32434_wdt_fops = { .llseek = no_llseek, .write = rc32434_wdt_write, .unlocked_ioctl = rc32434_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = rc32434_wdt_open, .release = rc32434_wdt_release, }; diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 2e608ae6cbc7..57187efeb86f 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c @@ -199,6 +199,7 @@ static const struct file_operations rdc321x_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = rdc321x_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = rdc321x_wdt_open, .write = rdc321x_wdt_write, .release = rdc321x_wdt_release, diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index b35f7be20c00..dc3c06a92f93 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -163,6 +163,7 @@ static const struct file_operations riowd_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = riowd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = riowd_open, .write = riowd_write, .release = riowd_release, diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index cbd8c957182f..9b93be00109f 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -141,6 +141,7 @@ static const struct file_operations sa1100dog_fops = { .llseek = no_llseek, .write = sa1100dog_write, .unlocked_ioctl = sa1100dog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sa1100dog_open, .release = sa1100dog_release, }; diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 202fc8d8ca5f..da2dad00d473 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -237,6 +237,7 @@ static const struct file_operations sbwdog_fops = { .llseek = no_llseek, .write = sbwdog_write, .unlocked_ioctl = sbwdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sbwdog_open, .release = sbwdog_release, }; diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index c3151642694c..f2cbe6d880a8 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c @@ -280,6 +280,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c index 12cdee7d5069..0bf583b76e6b 100644 --- a/drivers/watchdog/sbc7240_wdt.c +++ b/drivers/watchdog/sbc7240_wdt.c @@ -211,6 +211,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c index 86828c28843f..5e3a9ddb952e 100644 --- a/drivers/watchdog/sbc_epx_c3.c +++ b/drivers/watchdog/sbc_epx_c3.c @@ -156,6 +156,7 @@ static const struct file_operations epx_c3_fops = { .llseek = no_llseek, .write = epx_c3_write, .unlocked_ioctl = epx_c3_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = epx_c3_open, .release = epx_c3_release, }; diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c index 3822a60a8d2b..1b20b33879c4 100644 --- a/drivers/watchdog/sbc_fitpc2_wdt.c +++ b/drivers/watchdog/sbc_fitpc2_wdt.c @@ -186,6 +186,7 @@ static const struct file_operations fitpc2_wdt_fops = { .llseek = no_llseek, .write = fitpc2_wdt_write, .unlocked_ioctl = fitpc2_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = fitpc2_wdt_open, .release = fitpc2_wdt_release, }; diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 960385a766b3..9673eb12dacd 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -307,6 +307,7 @@ static const struct file_operations sc1200wdt_fops = { .llseek = no_llseek, .write = sc1200wdt_write, .unlocked_ioctl = sc1200wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sc1200wdt_open, .release = sc1200wdt_release, }; diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index a612128c5f80..fbe79bcc9297 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -336,6 +336,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 3612f1df381b..83949a385f62 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c @@ -337,6 +337,7 @@ static const struct file_operations sch311x_wdt_fops = { .llseek = no_llseek, .write = sch311x_wdt_write, .unlocked_ioctl = sch311x_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sch311x_wdt_open, .release = sch311x_wdt_close, }; diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c index 46268309ee9b..c94098acb78f 100644 --- a/drivers/watchdog/scx200_wdt.c +++ b/drivers/watchdog/scx200_wdt.c @@ -201,6 +201,7 @@ static const struct file_operations scx200_wdt_fops = { .llseek = no_llseek, .write = scx200_wdt_write, .unlocked_ioctl = scx200_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = scx200_wdt_open, .release = scx200_wdt_release, }; diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index f5713030d0f7..43de56acd767 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -505,6 +505,7 @@ static const struct file_operations wb_smsc_wdt_fops = { .llseek = no_llseek, .write = wb_smsc_wdt_write, .unlocked_ioctl = wb_smsc_wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wb_smsc_wdt_open, .release = wb_smsc_wdt_release, }; diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 6eb5185d6ea6..6b3b667e6f23 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c @@ -304,6 +304,7 @@ static const struct file_operations wdt_fops = { .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, + .compat_ioctl = compat_ptr_ioctl, }; static struct miscdevice wdt_miscdev = { diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c index 16e9cbe72acc..5212e68c6b01 100644 --- a/drivers/watchdog/w83977f_wdt.c +++ b/drivers/watchdog/w83977f_wdt.c @@ -446,6 +446,7 @@ static const struct file_operations wdt_fops = { .llseek = no_llseek, .write = wdt_write, .unlocked_ioctl = wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdt_open, .release = wdt_release, }; diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c index 6d2071a0590d..a6925847f76f 100644 --- a/drivers/watchdog/wafer5823wdt.c +++ b/drivers/watchdog/wafer5823wdt.c @@ -230,6 +230,7 @@ static const struct file_operations wafwdt_fops = { .llseek = no_llseek, .write = wafwdt_write, .unlocked_ioctl = wafwdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wafwdt_open, .release = wafwdt_close, }; diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index dbd2ad4c9294..3858094ca6ba 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -933,6 +933,7 @@ static const struct file_operations watchdog_fops = { .owner = THIS_MODULE, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = watchdog_open, .release = watchdog_release, }; diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index 6ad7edb4a712..184a06a74f83 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c @@ -472,6 +472,7 @@ static const struct file_operations wdrtas_fops = { .llseek = no_llseek, .write = wdrtas_write, .unlocked_ioctl = wdrtas_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdrtas_open, .release = wdrtas_close, }; diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 7d278b37e083..f9054cb0f8e2 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -523,6 +523,7 @@ static const struct file_operations wdt_fops = { .llseek = no_llseek, .write = wdt_write, .unlocked_ioctl = wdt_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdt_open, .release = wdt_release, }; diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c index eb729d704836..e60993d0767e 100644 --- a/drivers/watchdog/wdt285.c +++ b/drivers/watchdog/wdt285.c @@ -181,6 +181,7 @@ static const struct file_operations watchdog_fops = { .llseek = no_llseek, .write = watchdog_write, .unlocked_ioctl = watchdog_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = watchdog_open, .release = watchdog_release, }; diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c index 5c52c73e1839..066a4fb4d75b 100644 --- a/drivers/watchdog/wdt977.c +++ b/drivers/watchdog/wdt977.c @@ -422,6 +422,7 @@ static const struct file_operations wdt977_fops = { .llseek = no_llseek, .write = wdt977_write, .unlocked_ioctl = wdt977_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdt977_open, .release = wdt977_release, }; diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 66303ab95685..e528024faa41 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -566,6 +566,7 @@ static const struct file_operations wdtpci_fops = { .llseek = no_llseek, .write = wdtpci_write, .unlocked_ioctl = wdtpci_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = wdtpci_open, .release = wdtpci_release, }; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index b20228c19ccd..10ba2d9e20bc 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -412,17 +412,6 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN) COMPATIBLE_IOCTL(PPPIOCATTCHAN) COMPATIBLE_IOCTL(PPPIOCGCHAN) COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS) -/* Watchdog */ -COMPATIBLE_IOCTL(WDIOC_GETSUPPORT) -COMPATIBLE_IOCTL(WDIOC_GETSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETTEMP) -COMPATIBLE_IOCTL(WDIOC_SETOPTIONS) -COMPATIBLE_IOCTL(WDIOC_KEEPALIVE) -COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT) -COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT) -COMPATIBLE_IOCTL(WDIOC_SETPRETIMEOUT) -COMPATIBLE_IOCTL(WDIOC_GETPRETIMEOUT) }; /* -- cgit v1.2.3-59-g8ed1b From 98aaaec4a150c39219a8aaa68c3adc6eed443ea8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 14 Mar 2019 17:45:18 +0100 Subject: compat_ioctl: reimplement SG_IO handling There are two code locations that implement the SG_IO ioctl: the old sg.c driver, and the generic scsi_ioctl helper that is in turn used by multiple drivers. To eradicate the old compat_ioctl conversion handler for the SG_IO command, I implement a readable pair of put_sg_io_hdr() /get_sg_io_hdr() helper functions that can be used for both compat and native mode, and then I call this from both drivers. For the iovec handling, there is already a compat_import_iovec() function that can simply be called in place of import_iovec(). To avoid having to pass the compat/native state through multiple indirections, I mark the SG_IO command itself as compatible in fs/compat_ioctl.c and use in_compat_syscall() to figure out where we are called from. As a side-effect of this, the sg.c driver now also accepts the 32-bit sg_io_hdr format in compat mode using the read/write interface, not just ioctl. This should improve compatiblity with old 32-bit binaries, but it would break if any application intentionally passes the 64-bit data structure in compat mode here. Steffen Maier helped debug an issue in an earlier version of this patch. Cc: Steffen Maier Cc: linux-scsi@vger.kernel.org Cc: Doug Gilbert Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Signed-off-by: Arnd Bergmann --- block/scsi_ioctl.c | 132 +++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/sg.c | 19 ++++--- fs/compat_ioctl.c | 148 +------------------------------------------------ include/linux/blkdev.h | 2 + lib/iov_iter.c | 1 + 5 files changed, 143 insertions(+), 159 deletions(-) (limited to 'drivers') diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index f5e0ad65e86a..650bade5ea5a 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2001 Jens Axboe */ +#include #include #include #include @@ -327,7 +328,14 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, struct iov_iter i; struct iovec *iov = NULL; - ret = import_iovec(rq_data_dir(rq), +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + ret = compat_import_iovec(rq_data_dir(rq), + hdr->dxferp, hdr->iovec_count, + 0, &iov, &i); + else +#endif + ret = import_iovec(rq_data_dir(rq), hdr->dxferp, hdr->iovec_count, 0, &iov, &i); if (ret < 0) @@ -542,6 +550,122 @@ static inline int blk_send_start_stop(struct request_queue *q, return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data); } +#ifdef CONFIG_COMPAT +struct compat_sg_io_hdr { + compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ + compat_int_t dxfer_direction; /* [i] data transfer direction */ + unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char mx_sb_len; /* [i] max length to write to sbp */ + unsigned short iovec_count; /* [i] 0 implies no scatter gather */ + compat_uint_t dxfer_len; /* [i] byte count of data transfer */ + compat_uint_t dxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ + compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ + compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ + compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ + compat_int_t pack_id; /* [i->o] unused internally (normally) */ + compat_uptr_t usr_ptr; /* [i->o] unused internally */ + unsigned char status; /* [o] scsi status */ + unsigned char masked_status; /* [o] shifted, masked scsi status */ + unsigned char msg_status; /* [o] messaging level data (optional) */ + unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ + unsigned short host_status; /* [o] errors from host adapter */ + unsigned short driver_status; /* [o] errors from software driver */ + compat_int_t resid; /* [o] dxfer_len - actual_transferred */ + compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ + compat_uint_t info; /* [o] auxiliary information */ +}; +#endif + +int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp) +{ +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) { + struct compat_sg_io_hdr hdr32 = { + .interface_id = hdr->interface_id, + .dxfer_direction = hdr->dxfer_direction, + .cmd_len = hdr->cmd_len, + .mx_sb_len = hdr->mx_sb_len, + .iovec_count = hdr->iovec_count, + .dxfer_len = hdr->dxfer_len, + .dxferp = (uintptr_t)hdr->dxferp, + .cmdp = (uintptr_t)hdr->cmdp, + .sbp = (uintptr_t)hdr->sbp, + .timeout = hdr->timeout, + .flags = hdr->flags, + .pack_id = hdr->pack_id, + .usr_ptr = (uintptr_t)hdr->usr_ptr, + .status = hdr->status, + .masked_status = hdr->masked_status, + .msg_status = hdr->msg_status, + .sb_len_wr = hdr->sb_len_wr, + .host_status = hdr->host_status, + .driver_status = hdr->driver_status, + .resid = hdr->resid, + .duration = hdr->duration, + .info = hdr->info, + }; + + if (copy_to_user(argp, &hdr32, sizeof(hdr32))) + return -EFAULT; + + return 0; + } +#endif + + if (copy_to_user(argp, hdr, sizeof(*hdr))) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL(put_sg_io_hdr); + +int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp) +{ +#ifdef CONFIG_COMPAT + struct compat_sg_io_hdr hdr32; + + if (in_compat_syscall()) { + if (copy_from_user(&hdr32, argp, sizeof(hdr32))) + return -EFAULT; + + *hdr = (struct sg_io_hdr) { + .interface_id = hdr32.interface_id, + .dxfer_direction = hdr32.dxfer_direction, + .cmd_len = hdr32.cmd_len, + .mx_sb_len = hdr32.mx_sb_len, + .iovec_count = hdr32.iovec_count, + .dxfer_len = hdr32.dxfer_len, + .dxferp = compat_ptr(hdr32.dxferp), + .cmdp = compat_ptr(hdr32.cmdp), + .sbp = compat_ptr(hdr32.sbp), + .timeout = hdr32.timeout, + .flags = hdr32.flags, + .pack_id = hdr32.pack_id, + .usr_ptr = compat_ptr(hdr32.usr_ptr), + .status = hdr32.status, + .masked_status = hdr32.masked_status, + .msg_status = hdr32.msg_status, + .sb_len_wr = hdr32.sb_len_wr, + .host_status = hdr32.host_status, + .driver_status = hdr32.driver_status, + .resid = hdr32.resid, + .duration = hdr32.duration, + .info = hdr32.info, + }; + + return 0; + } +#endif + + if (copy_from_user(hdr, argp, sizeof(*hdr))) + return -EFAULT; + + return 0; +} +EXPORT_SYMBOL(get_sg_io_hdr); + int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode, unsigned int cmd, void __user *arg) { @@ -581,14 +705,14 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod case SG_IO: { struct sg_io_hdr hdr; - err = -EFAULT; - if (copy_from_user(&hdr, arg, sizeof(hdr))) + err = get_sg_io_hdr(&hdr, arg); + if (err) break; err = sg_io(q, bd_disk, &hdr, mode); if (err == -EFAULT) break; - if (copy_to_user(arg, &hdr, sizeof(hdr))) + if (put_sg_io_hdr(&hdr, arg)) err = -EFAULT; break; } diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index cce757506383..8ae096af2667 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -447,8 +447,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) retval = -ENOMEM; goto free_old_hdr; } - retval =__copy_from_user - (new_hdr, buf, SZ_SG_IO_HDR); + retval = get_sg_io_hdr(new_hdr, buf); req_pack_id = new_hdr->pack_id; kfree(new_hdr); if (retval) { @@ -589,10 +588,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) } if (hp->masked_status || hp->host_status || hp->driver_status) hp->info |= SG_INFO_CHECK; - if (copy_to_user(buf, hp, SZ_SG_IO_HDR)) { - err = -EFAULT; - goto err_out; - } + err = put_sg_io_hdr(hp, buf); err_out: err2 = sg_finish_rem_req(srp); sg_remove_request(sfp, srp); @@ -735,7 +731,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, } srp->sg_io_owned = sg_io_owned; hp = &srp->header; - if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) { + if (get_sg_io_hdr(hp, buf)) { sg_remove_request(sfp, srp); return -EFAULT; } @@ -1797,7 +1793,14 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) struct iovec *iov = NULL; struct iov_iter i; - res = import_iovec(rw, hp->dxferp, iov_count, 0, &iov, &i); +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + res = compat_import_iovec(rw, hp->dxferp, iov_count, + 0, &iov, &i); + else +#endif + res = import_iovec(rw, hp->dxferp, iov_count, + 0, &iov, &i); if (res < 0) return res; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 10ba2d9e20bc..f279e77df256 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -64,151 +64,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_BLOCK -typedef struct sg_io_hdr32 { - compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ - compat_int_t dxfer_direction; /* [i] data transfer direction */ - unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ - unsigned char mx_sb_len; /* [i] max length to write to sbp */ - unsigned short iovec_count; /* [i] 0 implies no scatter gather */ - compat_uint_t dxfer_len; /* [i] byte count of data transfer */ - compat_uint_t dxferp; /* [i], [*io] points to data transfer memory - or scatter gather list */ - compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ - compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ - compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ - compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ - compat_int_t pack_id; /* [i->o] unused internally (normally) */ - compat_uptr_t usr_ptr; /* [i->o] unused internally */ - unsigned char status; /* [o] scsi status */ - unsigned char masked_status; /* [o] shifted, masked scsi status */ - unsigned char msg_status; /* [o] messaging level data (optional) */ - unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ - unsigned short host_status; /* [o] errors from host adapter */ - unsigned short driver_status; /* [o] errors from software driver */ - compat_int_t resid; /* [o] dxfer_len - actual_transferred */ - compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ - compat_uint_t info; /* [o] auxiliary information */ -} sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ - -typedef struct sg_iovec32 { - compat_uint_t iov_base; - compat_uint_t iov_len; -} sg_iovec32_t; - -static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count) -{ - sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1); - sg_iovec32_t __user *iov32 = dxferp; - int i; - - for (i = 0; i < iovec_count; i++) { - u32 base, len; - - if (get_user(base, &iov32[i].iov_base) || - get_user(len, &iov32[i].iov_len) || - put_user(compat_ptr(base), &iov[i].iov_base) || - put_user(len, &iov[i].iov_len)) - return -EFAULT; - } - - if (put_user(iov, &sgio->dxferp)) - return -EFAULT; - return 0; -} - -static int sg_ioctl_trans(struct file *file, unsigned int cmd, - sg_io_hdr32_t __user *sgio32) -{ - sg_io_hdr_t __user *sgio; - u16 iovec_count; - u32 data; - void __user *dxferp; - int err; - int interface_id; - - if (get_user(interface_id, &sgio32->interface_id)) - return -EFAULT; - if (interface_id != 'S') - return do_ioctl(file, cmd, (unsigned long)sgio32); - - if (get_user(iovec_count, &sgio32->iovec_count)) - return -EFAULT; - - { - void __user *top = compat_alloc_user_space(0); - void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) + - (iovec_count * sizeof(sg_iovec_t))); - if (new > top) - return -EINVAL; - - sgio = new; - } - - /* Ok, now construct. */ - if (copy_in_user(&sgio->interface_id, &sgio32->interface_id, - (2 * sizeof(int)) + - (2 * sizeof(unsigned char)) + - (1 * sizeof(unsigned short)) + - (1 * sizeof(unsigned int)))) - return -EFAULT; - - if (get_user(data, &sgio32->dxferp)) - return -EFAULT; - dxferp = compat_ptr(data); - if (iovec_count) { - if (sg_build_iovec(sgio, dxferp, iovec_count)) - return -EFAULT; - } else { - if (put_user(dxferp, &sgio->dxferp)) - return -EFAULT; - } - - { - unsigned char __user *cmdp; - unsigned char __user *sbp; - - if (get_user(data, &sgio32->cmdp)) - return -EFAULT; - cmdp = compat_ptr(data); - - if (get_user(data, &sgio32->sbp)) - return -EFAULT; - sbp = compat_ptr(data); - - if (put_user(cmdp, &sgio->cmdp) || - put_user(sbp, &sgio->sbp)) - return -EFAULT; - } - - if (copy_in_user(&sgio->timeout, &sgio32->timeout, - 3 * sizeof(int))) - return -EFAULT; - - if (get_user(data, &sgio32->usr_ptr)) - return -EFAULT; - if (put_user(compat_ptr(data), &sgio->usr_ptr)) - return -EFAULT; - - err = do_ioctl(file, cmd, (unsigned long) sgio); - - if (err >= 0) { - void __user *datap; - - if (copy_in_user(&sgio32->pack_id, &sgio->pack_id, - sizeof(int)) || - get_user(datap, &sgio->usr_ptr) || - put_user((u32)(unsigned long)datap, - &sgio32->usr_ptr) || - copy_in_user(&sgio32->status, &sgio->status, - (4 * sizeof(unsigned char)) + - (2 * sizeof(unsigned short)) + - (3 * sizeof(int)))) - err = -EFAULT; - } - - return err; -} - struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ char req_state; char orphan; @@ -358,6 +213,7 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) #endif #ifdef CONFIG_BLOCK /* SG stuff */ +COMPATIBLE_IOCTL(SG_IO) COMPATIBLE_IOCTL(SG_SET_TIMEOUT) COMPATIBLE_IOCTL(SG_GET_TIMEOUT) COMPATIBLE_IOCTL(SG_EMULATED_HOST) @@ -435,8 +291,6 @@ static long do_ioctl_trans(unsigned int cmd, case PPPIOCSACTIVE32: return ppp_sock_fprog_ioctl_trans(file, cmd, argp); #ifdef CONFIG_BLOCK - case SG_IO: - return sg_ioctl_trans(file, cmd, argp); case SG_GET_REQUEST_TABLE: return sg_grt_trans(file, cmd, argp); #endif diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f3ea78b0c91c..2c8cd22b176b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -870,6 +870,8 @@ extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t, unsigned int, void __user *); extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t, struct scsi_ioctl_command __user *); +extern int get_sg_io_hdr(struct sg_io_hdr *hdr, const void __user *argp); +extern int put_sg_io_hdr(const struct sg_io_hdr *hdr, void __user *argp); extern int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags); extern void blk_queue_exit(struct request_queue *q); diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 639d5e7014c1..ffb52f2c0ef4 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1678,6 +1678,7 @@ ssize_t compat_import_iovec(int type, *iov = p == *iov ? NULL : p; return n; } +EXPORT_SYMBOL(compat_import_iovec); #endif int import_single_range(int rw, void __user *buf, size_t len, -- cgit v1.2.3-59-g8ed1b From c7dc504e2ff78a0bed3c36a44dff73f523ce0132 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jun 2019 23:07:12 +0200 Subject: compat_ioctl: move SIOCOUTQ out of compat_ioctl.c All users of this call are in socket or tty code, so handling it there means we can avoid the table entry in fs/compat_ioctl.c. Reviewed-by: Greg Kroah-Hartman Cc: Eric Dumazet Cc: netdev@vger.kernel.org Cc: "David S. Miller" Signed-off-by: Arnd Bergmann --- drivers/tty/tty_io.c | 1 + fs/compat_ioctl.c | 2 -- net/socket.c | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 802c1210558f..c09691b20a25 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2755,6 +2755,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, int retval = -ENOIOCTLCMD; switch (cmd) { + case TIOCOUTQ: case TIOCSTI: case TIOCGWINSZ: case TIOCSWINSZ: diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index f279e77df256..d537888f3660 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -198,8 +198,6 @@ static int ppp_scompress(struct file *file, unsigned int cmd, #define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd), static unsigned int ioctl_pointer[] = { -/* Little t */ -COMPATIBLE_IOCTL(TIOCOUTQ) #ifdef CONFIG_BLOCK /* Big S */ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) diff --git a/net/socket.c b/net/socket.c index a60f48ab2130..371999a024fa 100644 --- a/net/socket.c +++ b/net/socket.c @@ -100,6 +100,7 @@ #include #include #include +#include #include #include #include @@ -3452,6 +3453,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, case SIOCSARP: case SIOCGARP: case SIOCDARP: + case SIOCOUTQ: case SIOCOUTQNSD: case SIOCATMARK: return sock_do_ioctl(net, sock, cmd, arg); -- cgit v1.2.3-59-g8ed1b From b7aff093e94daff1e6076393ed43b7c9651b2b43 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 6 Jun 2019 10:07:36 +0200 Subject: tty: handle compat PPP ioctls Multiple tty devices are have tty devices that handle the PPPIOCGUNIT and PPPIOCGCHAN ioctls. To avoid adding a compat_ioctl handler to each of those, add it directly in tty_compat_ioctl so we can remove the calls from fs/compat_ioctl.c. Reviewed-by: Greg Kroah-Hartman Cc: Paul Mackerras Signed-off-by: Arnd Bergmann --- drivers/tty/tty_io.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c09691b20a25..a81807b394d1 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -87,6 +87,7 @@ #include #include #include +#include #include #include #include @@ -2811,6 +2812,9 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, #endif case TIOCGSOFTCAR: case TIOCSSOFTCAR: + + case PPPIOCGCHAN: + case PPPIOCGUNIT: return tty_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); case TIOCCONS: case TIOCEXCL: -- cgit v1.2.3-59-g8ed1b From 3e859adf3643c2da9765cd5088170738d7918567 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 17 Apr 2019 23:48:01 -0400 Subject: compat_ioctl: unify copy-in of ppp filters Now that isdn4linux is gone, the is only one implementation of PPPIOCSPASS and PPPIOCSACTIVE in ppp_generic.c, so this is where the compat_ioctl support should be implemented. The two commands are implemented in very similar ways, so introduce new helpers to allow sharing between the two and between native and compat mode. Signed-off-by: Al Viro [arnd: rebased, and added changelog text] Cc: netdev@vger.kernel.org Cc: linux-ppp@vger.kernel.org Cc: Paul Mackerras Cc: "David S. Miller" Signed-off-by: Arnd Bergmann --- drivers/net/ppp/ppp_generic.c | 169 +++++++++++++++++++++++++++--------------- fs/compat_ioctl.c | 37 --------- 2 files changed, 108 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 9a1b006904a7..7f8430e6b137 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -554,29 +554,58 @@ static __poll_t ppp_poll(struct file *file, poll_table *wait) } #ifdef CONFIG_PPP_FILTER -static int get_filter(void __user *arg, struct sock_filter **p) +static struct bpf_prog *get_filter(struct sock_fprog *uprog) +{ + struct sock_fprog_kern fprog; + struct bpf_prog *res = NULL; + int err; + + if (!uprog->len) + return NULL; + + /* uprog->len is unsigned short, so no overflow here */ + fprog.len = uprog->len * sizeof(struct sock_filter); + fprog.filter = memdup_user(uprog->filter, fprog.len); + if (IS_ERR(fprog.filter)) + return ERR_CAST(fprog.filter); + + err = bpf_prog_create(&res, &fprog); + kfree(fprog.filter); + + return err ? ERR_PTR(err) : res; +} + +static struct bpf_prog *ppp_get_filter(struct sock_fprog __user *p) { struct sock_fprog uprog; - struct sock_filter *code = NULL; - int len; - if (copy_from_user(&uprog, arg, sizeof(uprog))) - return -EFAULT; + if (copy_from_user(&uprog, p, sizeof(struct sock_fprog))) + return ERR_PTR(-EFAULT); + return get_filter(&uprog); +} - if (!uprog.len) { - *p = NULL; - return 0; - } +#ifdef CONFIG_COMPAT +struct sock_fprog32 { + unsigned short len; + compat_caddr_t filter; +}; - len = uprog.len * sizeof(struct sock_filter); - code = memdup_user(uprog.filter, len); - if (IS_ERR(code)) - return PTR_ERR(code); +#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) +#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32) - *p = code; - return uprog.len; +static struct bpf_prog *compat_ppp_get_filter(struct sock_fprog32 __user *p) +{ + struct sock_fprog32 uprog32; + struct sock_fprog uprog; + + if (copy_from_user(&uprog32, p, sizeof(struct sock_fprog32))) + return ERR_PTR(-EFAULT); + uprog.len = uprog32.len; + uprog.filter = compat_ptr(uprog32.filter); + return get_filter(&uprog); } -#endif /* CONFIG_PPP_FILTER */ +#endif +#endif static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -753,55 +782,25 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_PPP_FILTER case PPPIOCSPASS: - { - struct sock_filter *code; - - err = get_filter(argp, &code); - if (err >= 0) { - struct bpf_prog *pass_filter = NULL; - struct sock_fprog_kern fprog = { - .len = err, - .filter = code, - }; - - err = 0; - if (fprog.filter) - err = bpf_prog_create(&pass_filter, &fprog); - if (!err) { - ppp_lock(ppp); - if (ppp->pass_filter) - bpf_prog_destroy(ppp->pass_filter); - ppp->pass_filter = pass_filter; - ppp_unlock(ppp); - } - kfree(code); - } - break; - } case PPPIOCSACTIVE: { - struct sock_filter *code; + struct bpf_prog *filter = ppp_get_filter(argp); + struct bpf_prog **which; - err = get_filter(argp, &code); - if (err >= 0) { - struct bpf_prog *active_filter = NULL; - struct sock_fprog_kern fprog = { - .len = err, - .filter = code, - }; - - err = 0; - if (fprog.filter) - err = bpf_prog_create(&active_filter, &fprog); - if (!err) { - ppp_lock(ppp); - if (ppp->active_filter) - bpf_prog_destroy(ppp->active_filter); - ppp->active_filter = active_filter; - ppp_unlock(ppp); - } - kfree(code); + if (IS_ERR(filter)) { + err = PTR_ERR(filter); + break; } + if (cmd == PPPIOCSPASS) + which = &ppp->pass_filter; + else + which = &ppp->active_filter; + ppp_lock(ppp); + if (*which) + bpf_prog_destroy(*which); + *which = filter; + ppp_unlock(ppp); + err = 0; break; } #endif /* CONFIG_PPP_FILTER */ @@ -827,6 +826,51 @@ out: return err; } +#ifdef CONFIG_COMPAT +static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct ppp_file *pf; + int err = -ENOIOCTLCMD; + void __user *argp = (void __user *)arg; + + mutex_lock(&ppp_mutex); + + pf = file->private_data; + if (pf && pf->kind == INTERFACE) { + struct ppp *ppp = PF_TO_PPP(pf); + switch (cmd) { +#ifdef CONFIG_PPP_FILTER + case PPPIOCSPASS32: + case PPPIOCSACTIVE32: + { + struct bpf_prog *filter = compat_ppp_get_filter(argp); + struct bpf_prog **which; + + if (IS_ERR(filter)) { + err = PTR_ERR(filter); + break; + } + if (cmd == PPPIOCSPASS32) + which = &ppp->pass_filter; + else + which = &ppp->active_filter; + ppp_lock(ppp); + if (*which) + bpf_prog_destroy(*which); + *which = filter; + ppp_unlock(ppp); + err = 0; + break; + } +#endif /* CONFIG_PPP_FILTER */ + } + } + mutex_unlock(&ppp_mutex); + + return err; +} +#endif + static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, struct file *file, unsigned int cmd, unsigned long arg) { @@ -895,6 +939,9 @@ static const struct file_operations ppp_device_fops = { .write = ppp_write, .poll = ppp_poll, .unlocked_ioctl = ppp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ppp_compat_ioctl, +#endif .open = ppp_open, .release = ppp_release, .llseek = noop_llseek, diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index d537888f3660..eda41b2537f0 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -99,40 +99,6 @@ static int sg_grt_trans(struct file *file, } #endif /* CONFIG_BLOCK */ -struct sock_fprog32 { - unsigned short len; - compat_caddr_t filter; -}; - -#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) -#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32) - -static int ppp_sock_fprog_ioctl_trans(struct file *file, - unsigned int cmd, struct sock_fprog32 __user *u_fprog32) -{ - struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog)); - void __user *fptr64; - u32 fptr32; - u16 flen; - - if (get_user(flen, &u_fprog32->len) || - get_user(fptr32, &u_fprog32->filter)) - return -EFAULT; - - fptr64 = compat_ptr(fptr32); - - if (put_user(flen, &u_fprog64->len) || - put_user(fptr64, &u_fprog64->filter)) - return -EFAULT; - - if (cmd == PPPIOCSPASS32) - cmd = PPPIOCSPASS; - else - cmd = PPPIOCSACTIVE; - - return do_ioctl(file, cmd, (unsigned long) u_fprog64); -} - struct ppp_option_data32 { compat_caddr_t ptr; u32 length; @@ -285,9 +251,6 @@ static long do_ioctl_trans(unsigned int cmd, return ppp_gidle(file, cmd, argp); case PPPIOCSCOMPRESS32: return ppp_scompress(file, cmd, argp); - case PPPIOCSPASS32: - case PPPIOCSACTIVE32: - return ppp_sock_fprog_ioctl_trans(file, cmd, argp); #ifdef CONFIG_BLOCK case SG_GET_REQUEST_TABLE: return sg_grt_trans(file, cmd, argp); -- cgit v1.2.3-59-g8ed1b From 5b6c02df50fb28d23c733a24df5a06d0a3f28b93 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 18 Apr 2019 00:31:54 -0400 Subject: compat_ioctl: move PPPIOCSCOMPRESS to ppp_generic Rather than using a compat_alloc_user_space() buffer, moving this next to the native handler allows sharing most of the code, leaving only the user copy portion distinct. Signed-off-by: Al Viro Cc: netdev@vger.kernel.org Cc: linux-ppp@vger.kernel.org Cc: Paul Mackerras Cc: "David S. Miller" Signed-off-by: Arnd Bergmann --- drivers/net/ppp/ppp_generic.c | 53 +++++++++++++++++++++++++++++++------------ fs/compat_ioctl.c | 32 -------------------------- 2 files changed, 38 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 7f8430e6b137..fb8e0ac099b8 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -270,7 +270,7 @@ static void ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb); static struct sk_buff *ppp_mp_reconstruct(struct ppp *ppp); static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb); #endif /* CONFIG_PPP_MULTILINK */ -static int ppp_set_compress(struct ppp *ppp, unsigned long arg); +static int ppp_set_compress(struct ppp *ppp, struct ppp_option_data *data); static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound); static void ppp_ccp_closed(struct ppp *ppp); static struct compressor *find_compressor(int type); @@ -708,9 +708,14 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case PPPIOCSCOMPRESS: - err = ppp_set_compress(ppp, arg); + { + struct ppp_option_data data; + if (copy_from_user(&data, argp, sizeof(data))) + err = -EFAULT; + else + err = ppp_set_compress(ppp, &data); break; - + } case PPPIOCGUNIT: if (put_user(ppp->file.index, p)) break; @@ -827,6 +832,13 @@ out: } #ifdef CONFIG_COMPAT +struct ppp_option_data32 { + compat_uptr_t ptr; + u32 length; + compat_int_t transmit; +}; +#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) + static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ppp_file *pf; @@ -863,6 +875,21 @@ static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long break; } #endif /* CONFIG_PPP_FILTER */ + case PPPIOCSCOMPRESS32: + { + struct ppp_option_data32 data32; + if (copy_from_user(&data32, argp, sizeof(data32))) { + err = -EFAULT; + } else { + struct ppp_option_data data = { + .ptr = compat_ptr(data32.ptr), + .length = data32.length, + .transmit = data32.transmit + }; + err = ppp_set_compress(ppp, &data); + } + break; + } } } mutex_unlock(&ppp_mutex); @@ -2783,24 +2810,20 @@ ppp_output_wakeup(struct ppp_channel *chan) /* Process the PPPIOCSCOMPRESS ioctl. */ static int -ppp_set_compress(struct ppp *ppp, unsigned long arg) +ppp_set_compress(struct ppp *ppp, struct ppp_option_data *data) { - int err; + int err = -EFAULT; struct compressor *cp, *ocomp; - struct ppp_option_data data; void *state, *ostate; unsigned char ccp_option[CCP_MAX_OPTION_LENGTH]; - err = -EFAULT; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) - goto out; - if (data.length > CCP_MAX_OPTION_LENGTH) + if (data->length > CCP_MAX_OPTION_LENGTH) goto out; - if (copy_from_user(ccp_option, (void __user *) data.ptr, data.length)) + if (copy_from_user(ccp_option, data->ptr, data->length)) goto out; err = -EINVAL; - if (data.length < 2 || ccp_option[1] < 2 || ccp_option[1] > data.length) + if (data->length < 2 || ccp_option[1] < 2 || ccp_option[1] > data->length) goto out; cp = try_then_request_module( @@ -2810,8 +2833,8 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) goto out; err = -ENOBUFS; - if (data.transmit) { - state = cp->comp_alloc(ccp_option, data.length); + if (data->transmit) { + state = cp->comp_alloc(ccp_option, data->length); if (state) { ppp_xmit_lock(ppp); ppp->xstate &= ~SC_COMP_RUN; @@ -2829,7 +2852,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) module_put(cp->owner); } else { - state = cp->decomp_alloc(ccp_option, data.length); + state = cp->decomp_alloc(ccp_option, data->length); if (state) { ppp_recv_lock(ppp); ppp->rstate &= ~SC_DECOMP_RUN; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index eda41b2537f0..0b5a732d7afd 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -99,13 +99,6 @@ static int sg_grt_trans(struct file *file, } #endif /* CONFIG_BLOCK */ -struct ppp_option_data32 { - compat_caddr_t ptr; - u32 length; - compat_int_t transmit; -}; -#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) - struct ppp_idle32 { compat_time_t xmit_idle; compat_time_t recv_idle; @@ -133,29 +126,6 @@ static int ppp_gidle(struct file *file, unsigned int cmd, return err; } -static int ppp_scompress(struct file *file, unsigned int cmd, - struct ppp_option_data32 __user *odata32) -{ - struct ppp_option_data __user *odata; - __u32 data; - void __user *datap; - - odata = compat_alloc_user_space(sizeof(*odata)); - - if (get_user(data, &odata32->ptr)) - return -EFAULT; - - datap = compat_ptr(data); - if (put_user(datap, &odata->ptr)) - return -EFAULT; - - if (copy_in_user(&odata->length, &odata32->length, - sizeof(__u32) + sizeof(int))) - return -EFAULT; - - return do_ioctl(file, PPPIOCSCOMPRESS, (unsigned long) odata); -} - /* * simple reversible transform to make our table more evenly * distributed after sorting. @@ -249,8 +219,6 @@ static long do_ioctl_trans(unsigned int cmd, switch (cmd) { case PPPIOCGIDLE32: return ppp_gidle(file, cmd, argp); - case PPPIOCSCOMPRESS32: - return ppp_scompress(file, cmd, argp); #ifdef CONFIG_BLOCK case SG_GET_REQUEST_TABLE: return sg_grt_trans(file, cmd, argp); -- cgit v1.2.3-59-g8ed1b From 17c7e7f407085f510a815c0c99b3fd25d5b13110 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 16 Apr 2019 22:19:44 +0200 Subject: compat_ioctl: handle PPPIOCGIDLE for 64-bit time_t The ppp_idle structure is defined in terms of __kernel_time_t, which is defined as 'long' on all architectures, and this usage is not affected by the y2038 problem since it transports a time interval rather than an absolute time. However, the ppp user space defines the same structure as time_t, which may be 64-bit wide on new libc versions even on 32-bit architectures. It's easy enough to just handle both possible structure layouts on all architectures, to deal with the possibility that a user space ppp implementation comes with its own ppp_idle structure definition, as well as to document the fact that the driver is y2038-safe. Doing this also avoids the need for a special compat mode translation, since 32-bit and 64-bit kernels now support the same interfaces. The old 32-bit structure is also available on native 64-bit architectures now, but this is harmless. Cc: netdev@vger.kernel.org Cc: linux-ppp@vger.kernel.org Cc: Paul Mackerras Cc: "David S. Miller" Signed-off-by: Arnd Bergmann --- Documentation/networking/ppp_generic.txt | 2 ++ drivers/net/ppp/ppp_generic.c | 19 +++++++++++----- fs/compat_ioctl.c | 38 +++++--------------------------- include/uapi/linux/ppp-ioctl.h | 2 ++ include/uapi/linux/ppp_defs.h | 14 ++++++++++++ 5 files changed, 37 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/ppp_generic.txt b/Documentation/networking/ppp_generic.txt index 61daf4b39600..fd563aff5fc9 100644 --- a/Documentation/networking/ppp_generic.txt +++ b/Documentation/networking/ppp_generic.txt @@ -378,6 +378,8 @@ an interface unit are: CONFIG_PPP_FILTER option is enabled, the set of packets which reset the transmit and receive idle timers is restricted to those which pass the `active' packet filter. + Two versions of this command exist, to deal with user space + expecting times as either 32-bit or 64-bit time_t seconds. * PPPIOCSMAXCID sets the maximum connection-ID parameter (and thus the number of connection slots) for the TCP header compressor and diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index fb8e0ac099b8..ce4dd45c541d 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -612,7 +612,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct ppp_file *pf; struct ppp *ppp; int err = -EFAULT, val, val2, i; - struct ppp_idle idle; + struct ppp_idle32 idle32; + struct ppp_idle64 idle64; struct npioctl npi; int unit, cflags; struct slcompress *vj; @@ -735,10 +736,18 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) err = 0; break; - case PPPIOCGIDLE: - idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ; - idle.recv_idle = (jiffies - ppp->last_recv) / HZ; - if (copy_to_user(argp, &idle, sizeof(idle))) + case PPPIOCGIDLE32: + idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ; + idle32.recv_idle = (jiffies - ppp->last_recv) / HZ; + if (copy_to_user(argp, &idle32, sizeof(idle32))) + break; + err = 0; + break; + + case PPPIOCGIDLE64: + idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ; + idle64.recv_idle = (jiffies - ppp->last_recv) / HZ; + if (copy_to_user(argp, &idle64, sizeof(idle64))) break; err = 0; break; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 0b5a732d7afd..5e59101ef981 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -52,6 +52,7 @@ #include +#ifdef CONFIG_BLOCK static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int err; @@ -63,7 +64,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return vfs_ioctl(file, cmd, arg); } -#ifdef CONFIG_BLOCK struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ char req_state; char orphan; @@ -99,33 +99,6 @@ static int sg_grt_trans(struct file *file, } #endif /* CONFIG_BLOCK */ -struct ppp_idle32 { - compat_time_t xmit_idle; - compat_time_t recv_idle; -}; -#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) - -static int ppp_gidle(struct file *file, unsigned int cmd, - struct ppp_idle32 __user *idle32) -{ - struct ppp_idle __user *idle; - __kernel_time_t xmit, recv; - int err; - - idle = compat_alloc_user_space(sizeof(*idle)); - - err = do_ioctl(file, PPPIOCGIDLE, (unsigned long) idle); - - if (!err) { - if (get_user(xmit, &idle->xmit_idle) || - get_user(recv, &idle->recv_idle) || - put_user(xmit, &idle32->xmit_idle) || - put_user(recv, &idle32->recv_idle)) - err = -EFAULT; - } - return err; -} - /* * simple reversible transform to make our table more evenly * distributed after sorting. @@ -192,7 +165,8 @@ COMPATIBLE_IOCTL(PPPIOCGDEBUG) COMPATIBLE_IOCTL(PPPIOCSDEBUG) /* PPPIOCSPASS is translated */ /* PPPIOCSACTIVE is translated */ -/* PPPIOCGIDLE is translated */ +COMPATIBLE_IOCTL(PPPIOCGIDLE32) +COMPATIBLE_IOCTL(PPPIOCGIDLE64) COMPATIBLE_IOCTL(PPPIOCNEWUNIT) COMPATIBLE_IOCTL(PPPIOCATTACH) COMPATIBLE_IOCTL(PPPIOCDETACH) @@ -214,16 +188,14 @@ COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS) static long do_ioctl_trans(unsigned int cmd, unsigned long arg, struct file *file) { +#ifdef CONFIG_BLOCK void __user *argp = compat_ptr(arg); switch (cmd) { - case PPPIOCGIDLE32: - return ppp_gidle(file, cmd, argp); -#ifdef CONFIG_BLOCK case SG_GET_REQUEST_TABLE: return sg_grt_trans(file, cmd, argp); -#endif } +#endif return -ENOIOCTLCMD; } diff --git a/include/uapi/linux/ppp-ioctl.h b/include/uapi/linux/ppp-ioctl.h index 88b5f9990320..7bd2a5a75348 100644 --- a/include/uapi/linux/ppp-ioctl.h +++ b/include/uapi/linux/ppp-ioctl.h @@ -104,6 +104,8 @@ struct pppol2tp_ioc_stats { #define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */ #define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */ #define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ +#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) /* 32-bit times */ +#define PPPIOCGIDLE64 _IOR('t', 63, struct ppp_idle64) /* 64-bit times */ #define PPPIOCNEWUNIT _IOWR('t', 62, int) /* create new ppp unit */ #define PPPIOCATTACH _IOW('t', 61, int) /* attach to ppp unit */ #define PPPIOCDETACH _IOW('t', 60, int) /* obsolete, do not use */ diff --git a/include/uapi/linux/ppp_defs.h b/include/uapi/linux/ppp_defs.h index fff51b91b409..0039fa39a358 100644 --- a/include/uapi/linux/ppp_defs.h +++ b/include/uapi/linux/ppp_defs.h @@ -142,10 +142,24 @@ struct ppp_comp_stats { /* * The following structure records the time in seconds since * the last NP packet was sent or received. + * + * Linux implements both 32-bit and 64-bit time_t versions + * for compatibility with user space that defines ppp_idle + * based on the libc time_t. */ struct ppp_idle { __kernel_time_t xmit_idle; /* time since last NP packet sent */ __kernel_time_t recv_idle; /* time since last NP packet received */ }; +struct ppp_idle32 { + __s32 xmit_idle; /* time since last NP packet sent */ + __s32 recv_idle; /* time since last NP packet received */ +}; + +struct ppp_idle64 { + __s64 xmit_idle; /* time since last NP packet sent */ + __s64 recv_idle; /* time since last NP packet received */ +}; + #endif /* _UAPI_PPP_DEFS_H_ */ -- cgit v1.2.3-59-g8ed1b From 8f5d9f2ce3020be1a7924b4cc4a1f51164f2c0b7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 26 Jul 2019 15:21:39 +0200 Subject: compat_ioctl: ppp: move simple commands into ppp_generic.c All ppp commands that are not already handled in ppp_compat_ioctl() are compatible, so they can now handled by calling the native ppp_ioctl() directly. Without CONFIG_BLOCK, the generic compat_ioctl table is now empty, so add a check to avoid a build failure in the looking function for that configuration. Cc: netdev@vger.kernel.org Cc: linux-ppp@vger.kernel.org Cc: Paul Mackerras Cc: "David S. Miller" Signed-off-by: Arnd Bergmann --- drivers/net/ppp/ppp_generic.c | 4 ++++ fs/compat_ioctl.c | 36 ++++-------------------------------- 2 files changed, 8 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index ce4dd45c541d..267fe2c58087 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -903,6 +903,10 @@ static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long } mutex_unlock(&ppp_mutex); + /* all other commands have compatible arguments */ + if (err == -ENOIOCTLCMD) + err = ppp_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); + return err; } #endif diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 5e59101ef981..3cf8b6d113c3 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -144,38 +144,6 @@ COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) #endif -/* PPP stuff */ -COMPATIBLE_IOCTL(PPPIOCGFLAGS) -COMPATIBLE_IOCTL(PPPIOCSFLAGS) -COMPATIBLE_IOCTL(PPPIOCGASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGUNIT) -COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGMRU) -COMPATIBLE_IOCTL(PPPIOCSMRU) -COMPATIBLE_IOCTL(PPPIOCSMAXCID) -COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCXFERUNIT) -/* PPPIOCSCOMPRESS is translated */ -COMPATIBLE_IOCTL(PPPIOCGNPMODE) -COMPATIBLE_IOCTL(PPPIOCSNPMODE) -COMPATIBLE_IOCTL(PPPIOCGDEBUG) -COMPATIBLE_IOCTL(PPPIOCSDEBUG) -/* PPPIOCSPASS is translated */ -/* PPPIOCSACTIVE is translated */ -COMPATIBLE_IOCTL(PPPIOCGIDLE32) -COMPATIBLE_IOCTL(PPPIOCGIDLE64) -COMPATIBLE_IOCTL(PPPIOCNEWUNIT) -COMPATIBLE_IOCTL(PPPIOCATTACH) -COMPATIBLE_IOCTL(PPPIOCDETACH) -COMPATIBLE_IOCTL(PPPIOCSMRRU) -COMPATIBLE_IOCTL(PPPIOCCONNECT) -COMPATIBLE_IOCTL(PPPIOCDISCONN) -COMPATIBLE_IOCTL(PPPIOCATTCHAN) -COMPATIBLE_IOCTL(PPPIOCGCHAN) -COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS) }; /* @@ -202,6 +170,7 @@ static long do_ioctl_trans(unsigned int cmd, static int compat_ioctl_check_table(unsigned int xcmd) { +#ifdef CONFIG_BLOCK int i; const int max = ARRAY_SIZE(ioctl_pointer) - 1; @@ -220,6 +189,9 @@ static int compat_ioctl_check_table(unsigned int xcmd) i--; return ioctl_pointer[i] == xcmd; +#else + return 0; +#endif } COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, -- cgit v1.2.3-59-g8ed1b From fd6c3d5accea8e7ed267b8a47ffecf4d4869ae0c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 24 Aug 2018 14:53:13 +0200 Subject: compat_ioctl: move SG_GET_REQUEST_TABLE handling SG_GET_REQUEST_TABLE is now the last ioctl command that needs a conversion handler. This is only used in a single file, so the implementation should be there. I'm trying to simplify it in the process, to get rid of the compat_alloc_user_space() and extra copy, by adding a put_compat_request_table() function instead, which copies the data in the right format to user space. Cc: linux-scsi@vger.kernel.org Cc: Doug Gilbert Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Signed-off-by: Arnd Bergmann --- drivers/scsi/sg.c | 40 +++++++++++++++++++++++++++++++++----- fs/compat_ioctl.c | 57 +------------------------------------------------------ 2 files changed, 36 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 8ae096af2667..9e4ef22b3579 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -889,6 +889,33 @@ sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo) } } +#ifdef CONFIG_COMPAT +struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ + char req_state; + char orphan; + char sg_io_owned; + char problem; + int pack_id; + compat_uptr_t usr_ptr; + unsigned int duration; + int unused; +}; + +static int put_compat_request_table(struct compat_sg_req_info __user *o, + struct sg_req_info *rinfo) +{ + int i; + for (i = 0; i < SG_MAX_QUEUE; i++) { + if (copy_to_user(o + i, rinfo + i, offsetof(sg_req_info_t, usr_ptr)) || + put_user((uintptr_t)rinfo[i].usr_ptr, &o[i].usr_ptr) || + put_user(rinfo[i].duration, &o[i].duration) || + put_user(rinfo[i].unused, &o[i].unused)) + return -EFAULT; + } + return 0; +} +#endif + static long sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) { @@ -1069,9 +1096,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) val = (sdp->device ? 1 : 0); return put_user(val, ip); case SG_GET_REQUEST_TABLE: - if (!access_ok(p, SZ_SG_REQ_INFO * SG_MAX_QUEUE)) - return -EFAULT; - else { + { sg_req_info_t *rinfo; rinfo = kcalloc(SG_MAX_QUEUE, SZ_SG_REQ_INFO, @@ -1081,8 +1106,13 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) read_lock_irqsave(&sfp->rq_list_lock, iflags); sg_fill_request_table(sfp, rinfo); read_unlock_irqrestore(&sfp->rq_list_lock, iflags); - result = __copy_to_user(p, rinfo, - SZ_SG_REQ_INFO * SG_MAX_QUEUE); + #ifdef CONFIG_COMPAT + if (in_compat_syscall()) + result = put_compat_request_table(p, rinfo); + else + #endif + result = copy_to_user(p, rinfo, + SZ_SG_REQ_INFO * SG_MAX_QUEUE); result = result ? -EFAULT : 0; kfree(rinfo); return result; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 3cf8b6d113c3..9ae90d728c0f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -52,53 +52,6 @@ #include -#ifdef CONFIG_BLOCK -static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int err; - - err = security_file_ioctl(file, cmd, arg); - if (err) - return err; - - return vfs_ioctl(file, cmd, arg); -} - -struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ - char req_state; - char orphan; - char sg_io_owned; - char problem; - int pack_id; - compat_uptr_t usr_ptr; - unsigned int duration; - int unused; -}; - -static int sg_grt_trans(struct file *file, - unsigned int cmd, struct compat_sg_req_info __user *o) -{ - int err, i; - sg_req_info_t __user *r; - r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE); - err = do_ioctl(file, cmd, (unsigned long)r); - if (err < 0) - return err; - for (i = 0; i < SG_MAX_QUEUE; i++) { - void __user *ptr; - int d; - - if (copy_in_user(o + i, r + i, offsetof(sg_req_info_t, usr_ptr)) || - get_user(ptr, &r[i].usr_ptr) || - get_user(d, &r[i].duration) || - put_user((u32)(unsigned long)(ptr), &o[i].usr_ptr) || - put_user(d, &o[i].duration)) - return -EFAULT; - } - return err; -} -#endif /* CONFIG_BLOCK */ - /* * simple reversible transform to make our table more evenly * distributed after sorting. @@ -121,6 +74,7 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) #ifdef CONFIG_BLOCK /* SG stuff */ COMPATIBLE_IOCTL(SG_IO) +COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) COMPATIBLE_IOCTL(SG_SET_TIMEOUT) COMPATIBLE_IOCTL(SG_GET_TIMEOUT) COMPATIBLE_IOCTL(SG_EMULATED_HOST) @@ -156,15 +110,6 @@ COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) static long do_ioctl_trans(unsigned int cmd, unsigned long arg, struct file *file) { -#ifdef CONFIG_BLOCK - void __user *argp = compat_ptr(arg); - - switch (cmd) { - case SG_GET_REQUEST_TABLE: - return sg_grt_trans(file, cmd, argp); - } -#endif - return -ENOIOCTLCMD; } -- cgit v1.2.3-59-g8ed1b From 1b114b0817cc1d4110a885ea7026e223df66ed71 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 15 Mar 2019 17:16:36 +0100 Subject: pktcdvd: add compat_ioctl handler pkt_ioctl() implements the generic SCSI_IOCTL_SEND_COMMAND and some cdrom ioctls by forwarding to the underlying block device. For compat_ioctl handling, this always takes a roundtrip through fs/compat_ioctl.c that we should try to avoid, at least for the compatible commands. CDROM_SEND_PACKET is an exception here, it requires special translation in compat_blkdev_driver_ioctl(). CDROM_LAST_WRITTEN has no compat handling at the moment. Cc: Jens Axboe Cc: linux-block@vger.kernel.org Signed-off-by: Arnd Bergmann --- drivers/block/pktcdvd.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 76457003f140..ee67bf929fac 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2663,6 +2663,28 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return ret; } +#ifdef CONFIG_COMPAT +static int pkt_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + /* compatible */ + case CDROMEJECT: + case CDROMMULTISESSION: + case CDROMREADTOCENTRY: + case SCSI_IOCTL_SEND_COMMAND: + return pkt_ioctl(bdev, mode, cmd, (unsigned long)compat_ptr(arg)); + + + /* FIXME: no handler so far */ + case CDROM_LAST_WRITTEN: + /* handled in compat_blkdev_driver_ioctl */ + case CDROM_SEND_PACKET: + default: + return -ENOIOCTLCMD; + } +} +#endif + static unsigned int pkt_check_events(struct gendisk *disk, unsigned int clearing) { @@ -2684,6 +2706,9 @@ static const struct block_device_operations pktcdvd_ops = { .open = pkt_open, .release = pkt_close, .ioctl = pkt_ioctl, +#ifdef CONFIG_COMPAT + .ioctl = pkt_compat_ioctl, +#endif .check_events = pkt_check_events, }; -- cgit v1.2.3-59-g8ed1b From 142b2ac82e31c174936c5719fa12ae28f51a55b7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 15 Mar 2019 13:46:11 +0100 Subject: scsi: sd: enable compat ioctls for sed-opal The sed_ioctl() function is written to be compatible between 32-bit and 64-bit processes, however compat mode is only wired up for nvme, not for sd. Add the missing call to sed_ioctl() in sd_compat_ioctl(). Fixes: d80210f25ff0 ("sd: add support for TCG OPAL self encrypting disks") Cc: linux-scsi@vger.kernel.org Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Signed-off-by: Arnd Bergmann --- drivers/scsi/sd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 50928bc266eb..5abdf03083ae 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1692,20 +1692,30 @@ static void sd_rescan(struct device *dev) static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device; + struct gendisk *disk = bdev->bd_disk; + struct scsi_disk *sdkp = scsi_disk(disk); + struct scsi_device *sdev = sdkp->device; + void __user *p = compat_ptr(arg); int error; + error = scsi_verify_blk_ioctl(bdev, cmd); + if (error < 0) + return error; + error = scsi_ioctl_block_when_processing_errors(sdev, cmd, (mode & FMODE_NDELAY) != 0); if (error) return error; + + if (is_sed_ioctl(cmd)) + return sed_ioctl(sdkp->opal_dev, cmd, p); /* * Let the static ioctl translation table take care of it. */ if (!sdev->host->hostt->compat_ioctl) return -ENOIOCTLCMD; - return sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg); + return sdev->host->hostt->compat_ioctl(sdev, cmd, p); } #endif -- cgit v1.2.3-59-g8ed1b