Hi Al,
It took me way longer than I had hoped to revisit this series, see https://lore.kernel.org/lkml/20180912150142.157913-1-arnd@arndb.de/ for the previously posted version.
I've come to the point where all conversion handlers and most COMPATIBLE_IOCTL() entries are gone from this file, but for now, this series only has the parts that have either been reviewed previously, or that are simple enough to include.
The main missing piece is the SG_IO/SG_GET_REQUEST_TABLE conversion. I'll post the patches I made for that later, as they need more testing and review from the scsi maintainers.
I hope you can still take these for the coming merge window, unless new problems come up.
Arnd
Arnd Bergmann (26): compat_ioctl: pppoe: fix PPPOEIOCSFWD handling compat_ioctl: move simple ppp command handling into driver compat_ioctl: avoid unused function warning for do_ioctl compat_ioctl: move PPPIOCSCOMPRESS32 to ppp-generic.c compat_ioctl: move PPPIOCSPASS32/PPPIOCSACTIVE32 to ppp_generic.c compat_ioctl: handle PPPIOCGIDLE for 64-bit time_t compat_ioctl: move rtc handling into rtc-dev.c compat_ioctl: add compat_ptr_ioctl() compat_ioctl: move drivers to compat_ptr_ioctl compat_ioctl: use correct compat_ptr() translation in drivers ceph: fix compat_ioctl for ceph_dir_operations compat_ioctl: move more drivers to compat_ptr_ioctl compat_ioctl: move tape handling into drivers compat_ioctl: move ATYFB_CLK handling to atyfb driver compat_ioctl: move isdn/capi ioctl translation into driver compat_ioctl: move rfcomm handlers into driver compat_ioctl: move hci_sock handlers into driver compat_ioctl: remove HCIUART handling compat_ioctl: remove HIDIO translation compat_ioctl: remove translation for sound ioctls compat_ioctl: remove IGNORE_IOCTL() compat_ioctl: remove /dev/random commands compat_ioctl: remove joystick ioctl translation compat_ioctl: remove PCI ioctl translation compat_ioctl: remove /dev/raw ioctl translation compat_ioctl: remove last RAID handling code
Documentation/networking/ppp_generic.txt | 2 + arch/um/drivers/hostaudio_kern.c | 1 + drivers/android/binder.c | 2 +- drivers/char/ppdev.c | 12 +- drivers/char/random.c | 1 + drivers/char/tpm/tpm_vtpm_proxy.c | 12 +- 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/firewire/core-cdev.c | 12 +- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/hid/hidraw.c | 4 +- drivers/hid/usbhid/hiddev.c | 11 +- drivers/hwtracing/stm/core.c | 12 +- drivers/ide/ide-tape.c | 31 +- drivers/iio/industrialio-core.c | 2 +- drivers/infiniband/core/uverbs_main.c | 4 +- drivers/isdn/capi/capi.c | 31 + drivers/isdn/i4l/isdn_ppp.c | 14 +- drivers/media/rc/lirc_dev.c | 4 +- drivers/mfd/cros_ec_dev.c | 4 +- drivers/misc/cxl/flash.c | 8 +- drivers/misc/genwqe/card_dev.c | 23 +- drivers/misc/mei/main.c | 22 +- drivers/misc/vmw_vmci/vmci_host.c | 2 +- drivers/mtd/ubi/cdev.c | 36 +- drivers/net/ppp/ppp_generic.c | 99 +++- drivers/net/ppp/pppoe.c | 7 + drivers/net/ppp/pptp.c | 3 + drivers/net/tap.c | 12 +- 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/rtc/dev.c | 13 +- drivers/rtc/rtc-vr41xx.c | 10 + drivers/s390/char/tape_char.c | 41 +- 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/megaraid/megaraid_mm.c | 28 +- drivers/scsi/osst.c | 34 +- drivers/scsi/pmcraid.c | 4 +- drivers/scsi/st.c | 35 +- drivers/staging/android/ion/ion.c | 4 +- drivers/staging/pi433/pi433_if.c | 12 +- 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/usb/core/devio.c | 16 +- drivers/usb/gadget/function/f_fs.c | 12 +- 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 +- drivers/video/fbdev/aty/atyfb_base.c | 12 +- drivers/virt/fsl_hypervisor.c | 2 +- fs/btrfs/super.c | 2 +- fs/ceph/dir.c | 1 + fs/ceph/file.c | 2 +- fs/compat_ioctl.c | 602 +------------------- fs/fat/file.c | 13 +- fs/fuse/dev.c | 2 +- fs/notify/fanotify/fanotify_user.c | 2 +- fs/userfaultfd.c | 2 +- include/linux/fs.h | 7 + include/linux/if_pppox.h | 2 + include/linux/mtio.h | 58 ++ include/uapi/linux/ppp-ioctl.h | 2 + include/uapi/linux/ppp_defs.h | 14 + net/bluetooth/hci_sock.c | 21 +- net/bluetooth/rfcomm/sock.c | 14 +- net/l2tp/l2tp_ppp.c | 3 + net/rfkill/core.c | 2 +- sound/core/oss/pcm_oss.c | 4 + sound/oss/dmasound/dmasound_core.c | 2 + 82 files changed, 452 insertions(+), 1034 deletions(-) create mode 100644 include/linux/mtio.h
Support for handling the PPPOEIOCSFWD ioctl in compat mode was added in linux-2.5.69 along with hundreds of other commands, but was always broken sincen only the structure is compatible, but the command number is not, due to the size being sizeof(size_t), or at first sizeof(sizeof((struct sockaddr_pppox)), which is different on 64-bit architectures.
Guillaume Nault adds:
And the implementation was broken until 2016 (see 29e73269aa4d ("pppoe: fix reference counting in PPPoE proxy")), and nobody ever noticed. I should probably have removed this ioctl entirely instead of fixing it. Clearly, it has never been used.
Fix it by defining a separate command code that matches the 32-bit version, and marking that one as compatible. As long as we keep the native ioctl, it seems best to also have the compat version working.
This should apply to all stable kernels.
Acked-by: Guillaume Nault g.nault@alphalink.fr Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/ppp/pppoe.c | 4 ++++ fs/compat_ioctl.c | 2 +- include/linux/if_pppox.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index f22639f0116a..c5e7435db86c 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -57,6 +57,7 @@ * */
+#include <linux/compat.h> #include <linux/string.h> #include <linux/module.h> #include <linux/kernel.h> @@ -784,6 +785,9 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, err = 0; break;
+#ifdef CONFIG_COMPAT + case PPPOEIOCSFWD32: +#endif case PPPOEIOCSFWD: { struct pppox_sock *relay_po; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 6e30949d9f77..f1065d116b55 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -639,7 +639,7 @@ COMPATIBLE_IOCTL(PPPIOCATTCHAN) COMPATIBLE_IOCTL(PPPIOCGCHAN) COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS) /* PPPOX */ -COMPATIBLE_IOCTL(PPPOEIOCSFWD) +COMPATIBLE_IOCTL(PPPOEIOCSFWD32) COMPATIBLE_IOCTL(PPPOEIOCDFWD) /* Big A */ /* sparc only */ diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h index ba7a9b0c7c57..d221f1465f41 100644 --- a/include/linux/if_pppox.h +++ b/include/linux/if_pppox.h @@ -85,6 +85,8 @@ extern void unregister_pppox_proto(int proto_num); extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */ extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+#define PPPOEIOCSFWD32 _IOW(0xB1 ,0, compat_size_t) + /* PPPoX socket states */ enum { PPPOX_NONE = 0, /* initial state */
There are multiple implementations of the PPP ioctl interface in the kernel:
- drivers/net/ppp/ppp_generic.c implements a generic interface for the /dev/ppp chardev used by some subdrivers. - drivers/net/ppp/pppox.c implements a socket based interface for pppoe, pptp and l2tp. - drivers/isdn/i4l/isdn_ppp.c is for the i4l ISDN stack
All ioctl commands in the respective functions are compatible between 32-bit and 64-bit kernels, so we can simply mark the handlers themselves as compatible and stop listing the commands individually.
Four commands (PPPIOCSCOMPRESS, PPPIOCSPASS, PPPIOCSACTIVE, and PPPIOCGIDLE) are incompatible on the user level but have a translation handler to make them compatible. I'm simplifying that compat handling in separate patches.
The PPPIOCGUNIT and PPPIOCGCHAN ioctl commands are special, they are implemented on various other file descriptors, so we have to keep them listed as COMPATIBLE_IOCTL().
For the isdn_ppp code, additional ioctl commands are needed that have never had working compat handling, so I'm leaving that part out: If they are remaining users of i4l's ippp, they are not using compat mode today, and are highly unlikely in the future before the last ISDN network gets shut down. I4L has been deprecated since 2002.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/ppp/ppp_generic.c | 1 + drivers/net/ppp/pppoe.c | 3 +++ drivers/net/ppp/pptp.c | 3 +++ fs/compat_ioctl.c | 31 ------------------------------- net/l2tp/l2tp_ppp.c | 3 +++ 5 files changed, 10 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index c708400fff4a..04252c3492ee 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -899,6 +899,7 @@ static const struct file_operations ppp_device_fops = { .write = ppp_write, .poll = ppp_poll, .unlocked_ioctl = ppp_ioctl, + .compat_ioctl = ppp_ioctl, .open = ppp_open, .release = ppp_release, .llseek = noop_llseek, diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index c5e7435db86c..5eccb49bcd2e 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -1124,6 +1124,9 @@ static const struct proto_ops pppoe_ops = { .recvmsg = pppoe_recvmsg, .mmap = sock_no_mmap, .ioctl = pppox_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = pppox_ioctl, +#endif };
static const struct pppox_proto pppoe_proto = { diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 50c60550f295..7cf56ad50d07 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -628,6 +628,9 @@ static const struct proto_ops pptp_ops = { .recvmsg = sock_no_recvmsg, .mmap = sock_no_mmap, .ioctl = pppox_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = pppox_ioctl, +#endif };
static const struct pppox_proto pppox_pptp_proto = { diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index f1065d116b55..54f26a9fa9f2 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -608,39 +608,8 @@ 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 */ -/* PPPIOCGIDLE is translated */ -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) -/* PPPOX */ -COMPATIBLE_IOCTL(PPPOEIOCSFWD32) -COMPATIBLE_IOCTL(PPPOEIOCDFWD) /* Big A */ /* sparc only */ /* Big Q for sound/OSS */ diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 04d9946dcdba..8ef66513fbe0 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -1686,6 +1686,9 @@ static const struct proto_ops pppol2tp_ops = { .recvmsg = pppol2tp_recvmsg, .mmap = sock_no_mmap, .ioctl = pppox_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = pppox_ioctl, +#endif };
static const struct pppox_proto pppol2tp_proto = {
On Tue, Apr 16, 2019 at 10:19:40PM +0200, Arnd Bergmann wrote:
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index c708400fff4a..04252c3492ee 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -899,6 +899,7 @@ static const struct file_operations ppp_device_fops = { .write = ppp_write, .poll = ppp_poll, .unlocked_ioctl = ppp_ioctl,
- .compat_ioctl = ppp_ioctl,
Oh? What happens on e.g. s390 with something like PPPIOCNEWUNIT? Current kernel: * no ->compat_ioctl() * ->unlock_ioctl() is present * found by compat_ioctl_check_table() * pass (unsigned long)compat_ptr(arg) to do_vfs_ioctl() * pass that to ppp_ioctl() * pass that to ppp_unattached_ioctl() * fetch int from (int __user *)compat_ptr(arg)
With your patch: * call ppp_ioctl() * pass arg to ppp_unattached_ioctl() * fetch int from (int __user *)arg
AFAICS, that's broken... Looking at that ppp_ioctl(), pointer to arch-independent type or ignored: PPPIOCNEWUNIT PPPIOCATTACH PPPIOCATTCHAN PPPIOCSMRU PPPIOCSFLAGS PPPIOCGFLAGS PPPIOCGUNIT PPPIOCSDEBUG PPPIOCSMAXCID PPPIOCCONNECT PPPIOCGDEBUG PPPIOCSMAXCID PPPIOCSMRRU PPPIOCDETACH PPPIOCDISCONN PPPIOCGASYNCMAP PPPIOCSASYNCMAP PPPIOCGRASYNCMAP PPPIOCSRASYNCMAP PPPIOCGXASYNCMAP PPPIOCSXASYNCMAP PPPIOCGNPMODE PPPIOCSNPMODE pointer to struct ppp_option_data (with further pointer-chasing in it): PPPIOCSCOMPRESS pointer to struct ppp_idle: PPPIOCGIDLE pointer to struct sock_filter (with hidden pointer-chasing, AFAICS): PPPIOCSPASS PPPIOCSACTIVE
Pretty much all of them take pointers. What's more, reaction to unknown is -ENOTTY, not -ENOIOCTLCM, so that patch will have prevent the translated ones from reaching do_ioctl_trans()
What am I missing here? Why not simply do
compat_ppp_ioctl() { PPPIOCSCOMPRESS32 => deal with it PPPIOCGIDLE32 => deal with it PPPIOCSPASS32 / PPPIOCSACTIVE32 => deal with it default: pass compat_ptr(arg) to ppp_ioctl() and be done with that }
with BPF-related bits (both compat and native) taken to e.g. net/core/bpf-ppp.c, picked by both generic and isdn? IDGI...
On Wed, Apr 17, 2019 at 11:13 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Tue, Apr 16, 2019 at 10:19:40PM +0200, Arnd Bergmann wrote:
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index c708400fff4a..04252c3492ee 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -899,6 +899,7 @@ static const struct file_operations ppp_device_fops = { .write = ppp_write, .poll = ppp_poll, .unlocked_ioctl = ppp_ioctl,
.compat_ioctl = ppp_ioctl,
Oh? What happens on e.g. s390 with something like PPPIOCNEWUNIT? Current kernel: * no ->compat_ioctl() * ->unlock_ioctl() is present * found by compat_ioctl_check_table() * pass (unsigned long)compat_ptr(arg) to do_vfs_ioctl() * pass that to ppp_ioctl() * pass that to ppp_unattached_ioctl() * fetch int from (int __user *)compat_ptr(arg)
With your patch: * call ppp_ioctl() * pass arg to ppp_unattached_ioctl() * fetch int from (int __user *)arg
AFAICS, that's broken...
Correct. I had added this patch to the series from an older set of patches (predating the compat_ptr_ioctl() series) , and did not check for this issue again. When I originally created the patch, I assumed that even on s390 it would be no problem.
Looking at that ppp_ioctl(), pointer to arch-independent type or ignored: PPPIOCNEWUNIT PPPIOCATTACH PPPIOCATTCHAN PPPIOCSMRU PPPIOCSFLAGS PPPIOCGFLAGS PPPIOCGUNIT PPPIOCSDEBUG PPPIOCSMAXCID PPPIOCCONNECT PPPIOCGDEBUG PPPIOCSMAXCID PPPIOCSMRRU PPPIOCDETACH PPPIOCDISCONN PPPIOCGASYNCMAP PPPIOCSASYNCMAP PPPIOCGRASYNCMAP PPPIOCSRASYNCMAP PPPIOCGXASYNCMAP PPPIOCSXASYNCMAP PPPIOCGNPMODE PPPIOCSNPMODE pointer to struct ppp_option_data (with further pointer-chasing in it): PPPIOCSCOMPRESS pointer to struct ppp_idle: PPPIOCGIDLE pointer to struct sock_filter (with hidden pointer-chasing, AFAICS): PPPIOCSPASS PPPIOCSACTIVE
Pretty much all of them take pointers. What's more, reaction to unknown is -ENOTTY, not -ENOIOCTLCM, so that patch will have prevent the translated ones from reaching do_ioctl_trans()
Good point, this patch sequence does break bisection.
What am I missing here? Why not simply do
compat_ppp_ioctl() { PPPIOCSCOMPRESS32 => deal with it PPPIOCGIDLE32 => deal with it PPPIOCSPASS32 / PPPIOCSACTIVE32 => deal with it default: pass compat_ptr(arg) to ppp_ioctl() and be done with that }
with BPF-related bits (both compat and native) taken to e.g. net/core/bpf-ppp.c, picked by both generic and isdn? IDGI...
I was trying to unify the native and compat code paths as much as possible here. Handling the four PPPIO*32 commands in compat_ppp_ioctl would either require duplicating large chunks of ppp_ioctl, or keeping the extra compat_alloc_user_space() copy from the existing implementation.
I'll try to come up with a different way to structure the patches.
Arnd
On Thu, Apr 18, 2019 at 12:03:07AM +0200, Arnd Bergmann wrote:
On Wed, Apr 17, 2019 at 11:13 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Tue, Apr 16, 2019 at 10:19:40PM +0200, Arnd Bergmann wrote:
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index c708400fff4a..04252c3492ee 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -899,6 +899,7 @@ static const struct file_operations ppp_device_fops = { .write = ppp_write, .poll = ppp_poll, .unlocked_ioctl = ppp_ioctl,
.compat_ioctl = ppp_ioctl,
Oh? What happens on e.g. s390 with something like PPPIOCNEWUNIT? Current kernel: * no ->compat_ioctl() * ->unlock_ioctl() is present * found by compat_ioctl_check_table() * pass (unsigned long)compat_ptr(arg) to do_vfs_ioctl() * pass that to ppp_ioctl() * pass that to ppp_unattached_ioctl() * fetch int from (int __user *)compat_ptr(arg)
With your patch: * call ppp_ioctl() * pass arg to ppp_unattached_ioctl() * fetch int from (int __user *)arg
AFAICS, that's broken...
Correct. I had added this patch to the series from an older set of patches (predating the compat_ptr_ioctl() series) , and did not check for this issue again. When I originally created the patch, I assumed that even on s390 it would be no problem.
Looking at that ppp_ioctl(), pointer to arch-independent type or ignored: PPPIOCNEWUNIT PPPIOCATTACH PPPIOCATTCHAN PPPIOCSMRU PPPIOCSFLAGS PPPIOCGFLAGS PPPIOCGUNIT PPPIOCSDEBUG PPPIOCSMAXCID PPPIOCCONNECT PPPIOCGDEBUG PPPIOCSMAXCID PPPIOCSMRRU PPPIOCDETACH PPPIOCDISCONN PPPIOCGASYNCMAP PPPIOCSASYNCMAP PPPIOCGRASYNCMAP PPPIOCSRASYNCMAP PPPIOCGXASYNCMAP PPPIOCSXASYNCMAP PPPIOCGNPMODE PPPIOCSNPMODE pointer to struct ppp_option_data (with further pointer-chasing in it): PPPIOCSCOMPRESS pointer to struct ppp_idle: PPPIOCGIDLE pointer to struct sock_filter (with hidden pointer-chasing, AFAICS): PPPIOCSPASS PPPIOCSACTIVE
Pretty much all of them take pointers. What's more, reaction to unknown is -ENOTTY, not -ENOIOCTLCM, so that patch will have prevent the translated ones from reaching do_ioctl_trans()
Good point, this patch sequence does break bisection.
What am I missing here? Why not simply do
compat_ppp_ioctl() { PPPIOCSCOMPRESS32 => deal with it PPPIOCGIDLE32 => deal with it PPPIOCSPASS32 / PPPIOCSACTIVE32 => deal with it default: pass compat_ptr(arg) to ppp_ioctl() and be done with that }
with BPF-related bits (both compat and native) taken to e.g. net/core/bpf-ppp.c, picked by both generic and isdn? IDGI...
I was trying to unify the native and compat code paths as much as possible here. Handling the four PPPIO*32 commands in compat_ppp_ioctl would either require duplicating large chunks of ppp_ioctl, or keeping the extra compat_alloc_user_space() copy from the existing implementation.
I'll try to come up with a different way to structure the patches.
Huh? Instead of case PPPIOCSCOMPRESS: err = ppp_set_compress(ppp, arg); break; in native, have struct ppp_option_data data; ... case PPPIOCSCOMPRESS: if (copy_from_user(&data, argp, sizeof(data))) err = -EFAULT; else err = ppp_set_compress(ppp, &data); break;
while in compat do struct ppp_option_data32 data32;
case PPPIOCSCOMPRESS32: if (copy_from_user(&data32, argp, sizeof(data32))) err = -EFAULT; else err = ppp_set_compress(ppp, &(struct ppp_option_data){ .ptr = compat_ptr(data32.ptr), .length = data32.length, .transmit = data32.transmit }); break;
PPPIOCGIDLE is small to start with - not a lot to copy there. And as for the filters... What you need is something like
struct bpf_prog *get_ppp_bpf(struct sock_fprog __user *p) { struct sock_fprog uprog; struct sock_fprog_kern fprog; struct sock_filter *code = NULL; struct bpf_prog *res; int err;
if (copy_from_user(&uprog, p, sizeof(uprog))) return ERR_PTR(-EFAULT);
if (!uprog.len) return NULL;
fprog.len = uprog.len * sizeof(struct sock_filter); code = fprog.filter = memdup_user(uprog.filter, fprog.len); if (IS_ERR(code)) return ERR_CAST(code);
err = bpf_prog_create(&res, &fprog); kfree(code);
if (err) return ERR_PTR(err); return res; } in net/core/ppp-filter.c (or in net/core/filter.c, for that matter, under appropriate ifdef)) with obvious compat counterpart next to it. Hell, turn the above into
static struct bpf_prog *__get_ppp_bpf(struct sock_fprog *kp) { struct sock_fprog_kern fprog; struct sock_filter *code = NULL; struct bpf_prog *res; int err;
if (!kp->len) return NULL;
fprog.len = kp->len * sizeof(struct sock_filter); code = fprog.filter = memdup_user(kp->filter, fprog.len); if (IS_ERR(code)) return ERR_CAST(code);
err = bpf_prog_create(&res, &fprog); kfree(code);
if (err) return ERR_PTR(err); return res; }
struct bpf_prog *get_ppp_bpf(struct sock_fprog __user *p) { struct sock_fprog uprog;
if (copy_from_user(&uprog, p, sizeof(uprog))) return ERR_PTR(-EFAULT); return __get_ppp_bpf(&uprog); }
struct bpf_prog *compat_get_ppp_bpf(struct sock_fprog32 __user *p) { struct sock_fprog uprog32;
if (copy_from_user(&uprog32, p, sizeof(uprog32))) return ERR_PTR(-EFAULT); return __get_ppp_bpf(&(struct sock_fprog){ .len = uprog32.len, .filter = compat_ptr(uprog32.filter)}); }
Then in native ioctl do case PPPIOCSPASS: case PPPIOCSACTIVE: { struct bpf_prog *filter = get_bpf_ppp(argp);
if (IS_ERR(filter)) { err = PTR_ERR(filter); } else { struct bpf_prog **which; 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; } in native and similar in compat, with get_bpf_ppp() replaced with call of compat_get_bpf_ppp() and ioctl numbers obviously adjusted. All there is to it... Helpers obviously shared with isdn and yes, all crap gone from fs/compat_ioctl.c...
Why would you want to duplicate large chunks of anything? The above is not even compile-tested, but... I can put together a patch if you wish. Or am I missing something here?
On Thu, Apr 18, 2019 at 12:53:00AM +0100, Al Viro wrote:
Why would you want to duplicate large chunks of anything? The above is not even compile-tested, but... I can put together a patch if you wish. Or am I missing something here?
Actually, there's another broken part - pppox. And that one is nastier - you've just lost everything outside of protocol family ioctls on those sockets. Try e.g. SIOCGIFMTU in 32bit process on those.
We really can't reuse native ->ioctl() there - proto family ->compat_ioctl() *must* return -ENOIOCTLCMD on everything it doesn't handle.
On Thu, Apr 18, 2019 at 1:53 AM Al Viro viro@zeniv.linux.org.uk wrote:
On Thu, Apr 18, 2019 at 12:03:07AM +0200, Arnd Bergmann wrote:
On Wed, Apr 17, 2019 at 11:13 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Tue, Apr 16, 2019 at 10:19:40PM +0200, Arnd Bergmann wrote:
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index c708400fff4a..04252c3492ee 100644
_ptr(arg) to ppp_ioctl() and be done with that
}
with BPF-related bits (both compat and native) taken to e.g. net/core/bpf-ppp.c, picked by both generic and isdn? IDGI...
I was trying to unify the native and compat code paths as much as possible here. Handling the four PPPIO*32 commands in compat_ppp_ioctl would either require duplicating large chunks of ppp_ioctl, or keeping the extra compat_alloc_user_space() copy from the existing implementation.
I'll try to come up with a different way to structure the patches.
Huh? Instead of case PPPIOCSCOMPRESS: err = ppp_set_compress(ppp, arg); break; in native, have struct ppp_option_data data; ... case PPPIOCSCOMPRESS: if (copy_from_user(&data, argp, sizeof(data))) err = -EFAULT; else err = ppp_set_compress(ppp, &data); break;
Right, I ended up with something similar before I saw your message.
in native and similar in compat, with get_bpf_ppp() replaced with call of compat_get_bpf_ppp() and ioctl numbers obviously adjusted. All there is to it... Helpers obviously shared with isdn and yes, all crap gone from fs/compat_ioctl.c...
I would still leave the ISDN side alone, aside from adding the 64-bit time_t support.
Why would you want to duplicate large chunks of anything? The above is not even compile-tested, but... I can put together a patch if you wish. Or am I missing something here?
I expected that the ppp_compat_ioctl() function would end up fairly complex, to duplicate the logic before the switch()/case.
What I have now is
static long ppp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ppp_file *pf; struct ppp *ppp; int err = -ENOIOCTLCMD; struct ppp_option_data32 data32; struct ppp_option_data data; void __user *argp = compat_ptr(arg);
mutex_lock(&ppp_mutex);
pf = file->private_data; if (!pf || pf->kind != INTERFACE) goto out;
ppp = PF_TO_PPP(pf); switch (cmd) { case PPPIOCSCOMPRESS32: if (copy_from_user(&data32, argp, sizeof(data32))) { err = -EFAULT; goto out; }
data.ptr = compat_ptr(data32.ptr); data.length = data32.length; data.transmit = data32.transmit;
err = ppp_set_compress(ppp, &data); break;
#ifdef CONFIG_PPP_FILTER case PPPIOCSPASS32: err = compat_get_sock_fprog(&uprog, argp); if (err) break; err = ppp_set_filter(ppp, &uprog, &ppp->pass_filter); break;
case PPPIOCSACTIVE32: err = compat_get_sock_fprog(&uprog, argp); if (err) break; err = ppp_set_filter(ppp, &uprog, &ppp->active_filter); break; #endif /* CONFIG_PPP_FILTER */
default: break; }
out: mutex_unlock(&ppp_mutex);
if (err == -ENOIOCTLCMD) err = ppp_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
return err; }
Which doesn't look nearly as bad as I had feared, but still is a larger change to the existing code than what I had before, so there is a bigger risk that I screwed up somewhere new.
Arnd
The users are becoming rarer, and when the remaining ones are all turned off, gcc warns about an unused function.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 54f26a9fa9f2..2772b539674d 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -79,7 +79,7 @@ get_user(val, srcptr) || put_user(val, dstptr); \ })
-static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static inline int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int err;
PPPIOCSCOMPRESS is only implemented in ppp_generic, so it's best to move the compat handling there. My first approach was to keep it in a new ppp_compat_ioctl() function, but it turned out to be much simpler to do it in the regular ioctl handler, by allowing both structure layouts to be handled directly there.
Aside from moving the code to the right place, this also avoids a round-trip through compat_alloc_user_space() allocated memory.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/ppp/ppp_generic.c | 40 ++++++++++++++++++++++++++++++----- fs/compat_ioctl.c | 32 ---------------------------- 2 files changed, 35 insertions(+), 37 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 04252c3492ee..8d211c9c2e4e 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -274,7 +274,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, unsigned long arg, bool compat); 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); @@ -557,6 +557,15 @@ static __poll_t ppp_poll(struct file *file, poll_table *wait) return mask; }
+#ifdef CONFIG_COMPAT +struct ppp_option_data32 { + compat_caddr_t ptr; + u32 length; + compat_int_t transmit; +}; +#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) +#endif + #ifdef CONFIG_PPP_FILTER static int get_filter(void __user *arg, struct sock_filter **p) { @@ -683,8 +692,14 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break;
case PPPIOCSCOMPRESS: - err = ppp_set_compress(ppp, arg); + err = ppp_set_compress(ppp, arg, false); + break; + +#ifdef CONFIG_COMPAT + case PPPIOCSCOMPRESS32: + err = ppp_set_compress(ppp, arg, true); break; +#endif
case PPPIOCGUNIT: if (put_user(ppp->file.index, p)) @@ -2739,7 +2754,7 @@ 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, unsigned long arg, bool compat) { int err; struct compressor *cp, *ocomp; @@ -2748,8 +2763,23 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) unsigned char ccp_option[CCP_MAX_OPTION_LENGTH];
err = -EFAULT; - if (copy_from_user(&data, (void __user *) arg, sizeof(data))) - goto out; +#ifdef CONFIG_COMPAT + if (compat) { + struct ppp_option_data32 data32; + + if (copy_from_user(&data32, (void __user *) arg, + sizeof(data32))) + goto out; + + data.ptr = compat_ptr(data32.ptr); + data.length = data32.length; + data.transmit = data32.transmit; + } else +#endif + { + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + goto out; + } if (data.length > CCP_MAX_OPTION_LENGTH) goto out; if (copy_from_user(ccp_option, (void __user *) data.ptr, data.length)) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 2772b539674d..a7cea8f9c771 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -305,13 +305,6 @@ static int ppp_sock_fprog_ioctl_trans(struct file *file, return do_ioctl(file, cmd, (unsigned long) u_fprog64); }
-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; @@ -339,29 +332,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); -} - #ifdef CONFIG_BLOCK struct mtget32 { compat_long_t mt_type; @@ -904,8 +874,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); case PPPIOCSPASS32: case PPPIOCSACTIVE32: return ppp_sock_fprog_ioctl_trans(file, cmd, argp);
On Tue, Apr 16, 2019 at 10:19:42PM +0200, Arnd Bergmann wrote:
+#ifdef CONFIG_COMPAT +struct ppp_option_data32 {
- compat_caddr_t ptr;
Huh? compat_uptr_t, surely? I realize that compat_ioctl.c is bogus that way right now, but let's not spread that crap into the places where it's harder to find...
err = -EFAULT;
- if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
goto out;
+#ifdef CONFIG_COMPAT
- if (compat) {
struct ppp_option_data32 data32;
if (copy_from_user(&data32, (void __user *) arg,
sizeof(data32)))
goto out;
data.ptr = compat_ptr(data32.ptr);
data.length = data32.length;
data.transmit = data32.transmit;
- } else
+#endif
- {
if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
goto out;
- }
*UGH*
Do that in caller, please. And sod the flag argument...
On Wed, Apr 17, 2019 at 11:16 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Tue, Apr 16, 2019 at 10:19:42PM +0200, Arnd Bergmann wrote:
+#ifdef CONFIG_COMPAT +struct ppp_option_data32 {
compat_caddr_t ptr;
Huh? compat_uptr_t, surely? I realize that compat_ioctl.c is bogus that way right now, but let's not spread that crap into the places where it's harder to find...
Ok, done.
err = -EFAULT;
if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
goto out;
+#ifdef CONFIG_COMPAT
if (compat) {
struct ppp_option_data32 data32;
if (copy_from_user(&data32, (void __user *) arg,
sizeof(data32)))
goto out;
data.ptr = compat_ptr(data32.ptr);
data.length = data32.length;
data.transmit = data32.transmit;
} else
+#endif
{
if (copy_from_user(&data, (void __user *) arg, sizeof(data)))
goto out;
}
*UGH*
Do that in caller, please. And sod the flag argument...
Ack, changed it now.
Arnd
PPPIOCSPASS and PPPIOCSACTIVE are implemented in ppp_generic and isdn_ppp, but the latter one doesn't work for compat mode in general, so we can move these two into the generic code.
Again, the best implementation I could come up with was to merge the compat handling into the regular ppp_ioctl() function and treating all ioctl commands as compatible.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/net/ppp/ppp_generic.c | 39 ++++++++++++++++++++++++++++++----- fs/compat_ioctl.c | 37 --------------------------------- 2 files changed, 34 insertions(+), 42 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 8d211c9c2e4e..b8a867fdd5ad 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -22,6 +22,7 @@ * ==FILEVERSION 20041108== */
+#include <linux/compat.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched/signal.h> @@ -567,14 +568,36 @@ struct ppp_option_data32 { #endif
#ifdef CONFIG_PPP_FILTER -static int get_filter(void __user *arg, struct sock_filter **p) +#ifdef CONFIG_COMPAT +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) +#endif + +static int get_filter(void __user *arg, struct sock_filter **p, bool compat) { struct sock_fprog uprog; struct sock_filter *code = NULL; int len;
- if (copy_from_user(&uprog, arg, sizeof(uprog))) - return -EFAULT; +#ifdef CONFIG_COMPAT + if (compat) { + struct sock_fprog32 uprog32; + + if (copy_from_user(&uprog32, arg, sizeof(uprog32))) + return -EFAULT; + + uprog.len = uprog32.len; + uprog.filter = compat_ptr(uprog32.filter); + } else +#endif + { + if (copy_from_user(&uprog, arg, sizeof(uprog))) + return -EFAULT; + }
if (!uprog.len) { *p = NULL; @@ -772,10 +795,13 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#ifdef CONFIG_PPP_FILTER case PPPIOCSPASS: +#ifdef CONFIG_COMPAT + case PPPIOCSPASS32: +#endif { struct sock_filter *code;
- err = get_filter(argp, &code); + err = get_filter(argp, &code, cmd != PPPIOCSPASS); if (err >= 0) { struct bpf_prog *pass_filter = NULL; struct sock_fprog_kern fprog = { @@ -798,10 +824,13 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } case PPPIOCSACTIVE: +#ifdef CONFIG_COMPAT + case PPPIOCSACTIVE32: +#endif { struct sock_filter *code;
- err = get_filter(argp, &code); + err = get_filter(argp, &code, cmd != PPPIOCSACTIVE); if (err >= 0) { struct bpf_prog *active_filter = NULL; struct sock_fprog_kern fprog = { diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index a7cea8f9c771..d507b7189958 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -271,40 +271,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_idle32 { compat_time_t xmit_idle; compat_time_t recv_idle; @@ -874,9 +840,6 @@ static long do_ioctl_trans(unsigned int cmd, switch (cmd) { case PPPIOCGIDLE32: return ppp_gidle(file, cmd, argp); - case PPPIOCSPASS32: - case PPPIOCSACTIVE32: - return ppp_sock_fprog_ioctl_trans(file, cmd, argp); #ifdef CONFIG_BLOCK case SG_IO: return sg_ioctl_trans(file, cmd, argp);
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.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- Documentation/networking/ppp_generic.txt | 2 ++ drivers/isdn/i4l/isdn_ppp.c | 14 ++++++++--- drivers/net/ppp/ppp_generic.c | 19 +++++++++++---- fs/compat_ioctl.c | 31 ------------------------ include/uapi/linux/ppp-ioctl.h | 2 ++ include/uapi/linux/ppp_defs.h | 14 +++++++++++ 6 files changed, 43 insertions(+), 39 deletions(-)
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/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index a7b275ea5de1..1f17126c5fa4 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c @@ -543,11 +543,19 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) } is->pppcfg = val; break; - case PPPIOCGIDLE: /* get idle time information */ + case PPPIOCGIDLE32: /* get idle time information */ if (lp) { - struct ppp_idle pidle; + struct ppp_idle32 pidle; pidle.xmit_idle = pidle.recv_idle = lp->huptimer; - if ((r = set_arg(argp, &pidle, sizeof(struct ppp_idle)))) + if ((r = set_arg(argp, &pidle, sizeof(struct ppp_idle32)))) + return r; + } + break; + case PPPIOCGIDLE64: /* get idle time information */ + if (lp) { + struct ppp_idle64 pidle; + pidle.xmit_idle = pidle.recv_idle = lp->huptimer; + if ((r = set_arg(argp, &pidle, sizeof(struct ppp_idle64)))) return r; } break; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index b8a867fdd5ad..712fa94650fe 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -619,7 +619,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; @@ -743,10 +744,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 d507b7189958..e6dbd956cf66 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -269,36 +269,7 @@ static int sg_grt_trans(struct file *file, } return err; } -#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; -} - -#ifdef CONFIG_BLOCK struct mtget32 { compat_long_t mt_type; compat_long_t mt_resid; @@ -838,8 +809,6 @@ static long do_ioctl_trans(unsigned int cmd, void __user *argp = compat_ptr(arg);
switch (cmd) { - case PPPIOCGIDLE32: - return ppp_gidle(file, cmd, argp); #ifdef CONFIG_BLOCK case SG_IO: return sg_ioctl_trans(file, cmd, argp); 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_ */
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.
Since the ioctl commands are either compatible or differ in both structure and command code between 32-bit and 64-bit, we can merge the compat handler into the native one and just implement the two common compat commands (RTC_IRQP_READ, RTC_IRQP_SET) there. The result is a slight change in behavior, as a native 64-bit process will now also handle the 32-bit commands (RTC_IRQP_SET32/RTC_IRQP_SET).
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 alexandre.belloni@bootlin.com Signed-off-by: Arnd Bergmann arnd@arndb.de --- 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 | 13 ++++++++- drivers/rtc/rtc-vr41xx.c | 10 +++++++ fs/compat_ioctl.c | 61 ++-------------------------------------- 3 files changed, 25 insertions(+), 59 deletions(-)
diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c index 1d006ef4bb57..a63779ccc8aa 100644 --- a/drivers/rtc/dev.c +++ b/drivers/rtc/dev.c @@ -13,6 +13,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/compat.h> #include <linux/module.h> #include <linux/rtc.h> #include <linux/sched/signal.h> @@ -359,10 +360,19 @@ static long rtc_dev_ioctl(struct file *file, mutex_unlock(&rtc->ops_lock); return rtc_update_irq_enable(rtc, 0);
+#ifdef CONFIG_64BIT +#define RTC_IRQP_SET32 _IOW('p', 0x0c, __u32) +#define RTC_IRQP_READ32 _IOR('p', 0x0b, __u32) + case RTC_IRQP_SET32: + err = rtc_irq_set_freq(rtc, arg); + break; + case RTC_IRQP_READ32: + err = put_user(rtc->irq_freq, (unsigned int __user *)uarg); + break; +#endif 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; @@ -434,6 +444,7 @@ static const struct file_operations rtc_dev_fops = { .read = rtc_dev_read, .poll = rtc_dev_poll, .unlocked_ioctl = rtc_dev_ioctl, + .compat_ioctl = compat_ptr_ioctl, .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 e66d0f63cee2..62c16a3b2d5c 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/compat.h> #include <linux/err.h> #include <linux/fs.h> #include <linux/init.h> @@ -79,6 +80,10 @@ 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) +#define RTC_EPOCH_SET32 _IOW('p', 0x0e, __u32) + static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
static DEFINE_SPINLOCK(rtc_lock); @@ -192,6 +197,11 @@ 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); + case RTC_EPOCH_SET32: +#endif case RTC_EPOCH_SET: /* Doesn't support before 1900 */ if (arg < 1900) diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index e6dbd956cf66..fee116e822d8 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -32,7 +32,6 @@ #include <linux/vt_kern.h> #include <linux/raw.h> #include <linux/blkdev.h> -#include <linux/rtc.h> #include <linux/pci.h> #include <linux/serial.h> #include <linux/ctype.h> @@ -343,37 +342,6 @@ static int mt_ioctl_trans(struct file *file, #define HCIUARTSETFLAGS _IOW('U', 203, int) #define HCIUARTGETFLAGS _IOR('U', 204, int)
-#define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) -#define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) -#define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) -#define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t) - -static int rtc_ioctl(struct file *file, - unsigned cmd, void __user *argp) -{ - unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp)); - int ret; - - if (valp == NULL) - return -EFAULT; - switch (cmd) { - case RTC_IRQP_READ32: - case RTC_EPOCH_READ32: - ret = do_ioctl(file, (cmd == RTC_IRQP_READ32) ? - RTC_IRQP_READ : RTC_EPOCH_READ, - (unsigned long)valp); - if (ret) - return ret; - return convert_in_user(valp, (unsigned int __user *)argp); - case RTC_IRQP_SET32: - return do_ioctl(file, RTC_IRQP_SET, (unsigned long)argp); - case RTC_EPOCH_SET32: - return do_ioctl(file, RTC_EPOCH_SET, (unsigned long)argp); - } - - return -ENOIOCTLCMD; -} - /* on ia32 l_start is on a 32-bit boundary */ #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) struct space_resv_32 { @@ -457,21 +425,6 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) /* Big V (don't complain on serial console) */ IGNORE_IOCTL(VT_OPENQRY) IGNORE_IOCTL(VT_GETMODE) -/* Little p (/dev/rtc, /dev/envctrl, etc.) */ -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) -COMPATIBLE_IOCTL(RTC_ALM_READ) -COMPATIBLE_IOCTL(RTC_RD_TIME) -COMPATIBLE_IOCTL(RTC_SET_TIME) -COMPATIBLE_IOCTL(RTC_WKALM_SET) -COMPATIBLE_IOCTL(RTC_WKALM_RD) /* * These two are only for the sbus rtc driver, but * hwclock tries them on every rtc device first when @@ -806,24 +759,16 @@ IGNORE_IOCTL(FBIOGCURSOR32) static long do_ioctl_trans(unsigned int cmd, unsigned long arg, struct file *file) { - void __user *argp = compat_ptr(arg); - switch (cmd) { #ifdef CONFIG_BLOCK case SG_IO: - return sg_ioctl_trans(file, cmd, argp); + return sg_ioctl_trans(file, cmd, compat_ptr(arg)); case SG_GET_REQUEST_TABLE: - return sg_grt_trans(file, cmd, argp); + return sg_grt_trans(file, cmd, compat_ptr(arg)); case MTIOCGET32: case MTIOCPOS32: - return mt_ioctl_trans(file, cmd, argp); + return mt_ioctl_trans(file, cmd, compat_ptr(arg)); #endif - /* Not implemented in the native kernel */ - case RTC_IRQP_READ32: - case RTC_IRQP_SET32: - case RTC_EPOCH_READ32: - case RTC_EPOCH_SET32: - return rtc_ioctl(file, cmd, argp); }
/*
Many drivers have ioctl() handlers that are completely compatible between 32-bit and 64-bit architectures, except for the argument that is passed down from user space and may have to be passed through compat_ptr() in order to become a valid 64-bit pointer.
Using ".compat_ptr = compat_ptr_ioctl" in file operations should let us simplify a lot of those drivers to avoid #ifdef checks, and convert additional drivers that don't have proper compat handling yet.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- v2: use compat_ptr_ioctl instead of generic_compat_ioctl_ptrarg, as suggested by Al Viro --- fs/compat_ioctl.c | 10 ++++++++++ include/linux/fs.h | 7 +++++++ 2 files changed, 17 insertions(+)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index fee116e822d8..ab2ff530313b 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -78,6 +78,16 @@ get_user(val, srcptr) || put_user(val, dstptr); \ })
+/* helper function to avoid trivial compat_ioctl() implementations */ +long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + if (!file->f_op->unlocked_ioctl) + return -ENOIOCTLCMD; + + return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +EXPORT_SYMBOL(compat_ptr_ioctl); + static inline int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int err; diff --git a/include/linux/fs.h b/include/linux/fs.h index dd28e7679089..dc4138314635 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1698,6 +1698,13 @@ int vfs_mkobj(struct dentry *, umode_t,
extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT +extern long compat_ptr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); +#else +#define compat_ptr_ioctl NULL +#endif + /* * VFS file helper functions. */
On Tue, Apr 16, 2019 at 10:19:46PM +0200, Arnd Bergmann wrote:
Many drivers have ioctl() handlers that are completely compatible between 32-bit and 64-bit architectures, except for the argument that is passed down from user space and may have to be passed through compat_ptr() in order to become a valid 64-bit pointer.
Using ".compat_ptr = compat_ptr_ioctl" in file operations should let us simplify a lot of those drivers to avoid #ifdef checks, and convert additional drivers that don't have proper compat handling yet.
You forgot to mention that it even gets the previous commit to build ;-) IOW, that needs to be reordered.
On Wed, Apr 17, 2019 at 11:19 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Tue, Apr 16, 2019 at 10:19:46PM +0200, Arnd Bergmann wrote:
Many drivers have ioctl() handlers that are completely compatible between 32-bit and 64-bit architectures, except for the argument that is passed down from user space and may have to be passed through compat_ptr() in order to become a valid 64-bit pointer.
Using ".compat_ptr = compat_ptr_ioctl" in file operations should let us simplify a lot of those drivers to avoid #ifdef checks, and convert additional drivers that don't have proper compat handling yet.
You forgot to mention that it even gets the previous commit to build ;-) IOW, that needs to be reordered.
Right. I had reordered the series multiple times and got this part wrong in the end.
Arnd
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 gregkh@linuxfoundation.org Reviewed-by: Jarkko Sakkinen jarkko.sakkinen@linux.intel.com Reviewed-by: Jason Gunthorpe jgg@mellanox.com Signed-off-by: Arnd Bergmann arnd@arndb.de --- 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(-)
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 1ae77b41050a..e96c8d9623e0 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -674,14 +674,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); @@ -790,9 +782,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 d74f3de74ae6..fb845f0a430b 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -675,20 +675,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 16a7045736a9..fb934680fdd3 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1659,14 +1659,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; @@ -1808,7 +1800,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 a746017fac17..ef4a1cd389d6 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -855,13 +855,6 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 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, @@ -871,9 +864,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 c7ba8acfd4d5..454da259f144 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -840,23 +840,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 87281b3695e6..cc6af92cdef0 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -535,24 +535,6 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) 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 * @@ -855,9 +837,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 947a8adbc799..265d34fa3efa 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -1091,36 +1091,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, @@ -1131,7 +1101,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 */ @@ -1139,13 +1109,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 2ea9b4976f4a..ebe425e65992 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 b2314636dc89..ab7dfc7c2917 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -935,16 +935,6 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return retval; }
-#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) @@ -1101,7 +1091,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 fa783531ee88..d75052b36584 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2568,18 +2568,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) @@ -2603,9 +2591,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 a3030cdf3c18..a5efe82584a5 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1200,15 +1200,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; @@ -1291,9 +1282,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, };
@@ -1572,15 +1561,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; @@ -1636,9 +1616,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, }; @@ -1703,24 +1681,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 df51a35cf537..1642b3573230 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1765,14 +1765,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; @@ -1808,9 +1800,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 618fb6461017..f9b14c39d89b 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1721,21 +1721,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 40589850eb33..61d4d98c8f70 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -298,21 +298,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 bb5fc0e9fbc2..9a86202678b6 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -716,23 +716,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 b3bed32946b1..f173d9261115 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -171,15 +171,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) && @@ -209,9 +200,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,
On Tue, 16 Apr 2019, Arnd Bergmann wrote:
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 gregkh@linuxfoundation.org Reviewed-by: Jarkko Sakkinen jarkko.sakkinen@linux.intel.com Reviewed-by: Jason Gunthorpe jgg@mellanox.com Signed-off-by: Arnd Bergmann arnd@arndb.de
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 +--------
For hiddev.c:
Reviewed-by: Jiri Kosina jkosina@suse.cz
On Tue, Apr 16, 2019 at 10:19:47PM +0200, Arnd Bergmann wrote:
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 gregkh@linuxfoundation.org Reviewed-by: Jarkko Sakkinen jarkko.sakkinen@linux.intel.com Reviewed-by: Jason Gunthorpe jgg@mellanox.com Signed-off-by: Arnd Bergmann arnd@arndb.de
Acked-by: Michael S. Tsirkin mst@redhat.com
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(-)
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 1ae77b41050a..e96c8d9623e0 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -674,14 +674,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); @@ -790,9 +782,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 d74f3de74ae6..fb845f0a430b 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -675,20 +675,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 16a7045736a9..fb934680fdd3 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1659,14 +1659,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; @@ -1808,7 +1800,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 a746017fac17..ef4a1cd389d6 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -855,13 +855,6 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 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, @@ -871,9 +864,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 c7ba8acfd4d5..454da259f144 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -840,23 +840,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 87281b3695e6..cc6af92cdef0 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -535,24 +535,6 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) 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
@@ -855,9 +837,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 947a8adbc799..265d34fa3efa 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -1091,36 +1091,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, @@ -1131,7 +1101,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 */ @@ -1139,13 +1109,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 2ea9b4976f4a..ebe425e65992 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 b2314636dc89..ab7dfc7c2917 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -935,16 +935,6 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return retval; } -#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) @@ -1101,7 +1091,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 fa783531ee88..d75052b36584 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2568,18 +2568,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) @@ -2603,9 +2591,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 a3030cdf3c18..a5efe82584a5 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1200,15 +1200,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; @@ -1291,9 +1282,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,
}; @@ -1572,15 +1561,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; @@ -1636,9 +1616,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,
}; @@ -1703,24 +1681,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 df51a35cf537..1642b3573230 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1765,14 +1765,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; @@ -1808,9 +1800,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 618fb6461017..f9b14c39d89b 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1721,21 +1721,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 40589850eb33..61d4d98c8f70 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -298,21 +298,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 bb5fc0e9fbc2..9a86202678b6 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -716,23 +716,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 b3bed32946b1..f173d9261115 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -171,15 +171,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) && @@ -209,9 +200,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,
-- 2.20.0
On Tue, Apr 16, 2019 at 10:19:47PM +0200, Arnd Bergmann wrote:
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 gregkh@linuxfoundation.org Reviewed-by: Jarkko Sakkinen jarkko.sakkinen@linux.intel.com Reviewed-by: Jason Gunthorpe jgg@mellanox.com Signed-off-by: Arnd Bergmann arnd@arndb.de
Acked-by: Michael S. Tsirkin mst@redhat.com
Acked-by: Tomas Winkler tomas.winkler@intel.com
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(-)
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 1ae77b41050a..e96c8d9623e0 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -674,14 +674,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); @@ -790,9 +782,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 d74f3de74ae6..fb845f0a430b 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -675,20 +675,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 16a7045736a9..fb934680fdd3 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1659,14 +1659,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; @@ -1808,7 +1800,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 a746017fac17..ef4a1cd389d6 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -855,13 +855,6 @@ static long hiddev_ioctl(struct file *file, unsigned int
cmd, unsigned long arg)
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, @@ -871,9 +864,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 c7ba8acfd4d5..454da259f144 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -840,23 +840,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 87281b3695e6..cc6af92cdef0 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -535,24 +535,6 @@ static long mei_ioctl(struct file *file, unsigned int
cmd, unsigned long data)
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
@@ -855,9 +837,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 947a8adbc799..265d34fa3efa 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -1091,36 +1091,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, @@ -1131,7 +1101,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 */ @@ -1139,13 +1109,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 2ea9b4976f4a..ebe425e65992 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 b2314636dc89..ab7dfc7c2917 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -935,16 +935,6 @@ pi433_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
return retval; }
-#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) @@ -1101,7 +1091,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 fa783531ee88..d75052b36584 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2568,18 +2568,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) @@ -2603,9 +2591,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 a3030cdf3c18..a5efe82584a5 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -1200,15 +1200,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; @@ -1291,9 +1282,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,
};
@@ -1572,15 +1561,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; @@ -1636,9 +1616,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,
}; @@ -1703,24 +1681,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 df51a35cf537..1642b3573230 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -1765,14 +1765,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; @@ -1808,9 +1800,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 618fb6461017..f9b14c39d89b 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1721,21 +1721,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 40589850eb33..61d4d98c8f70 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -298,21 +298,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 bb5fc0e9fbc2..9a86202678b6 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -716,23 +716,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 b3bed32946b1..f173d9261115 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -171,15 +171,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) && @@ -209,9 +200,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,
-- 2.20.0
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.
Acked-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Acked-by: Andrew Donnellan andrew.donnellan@au1.ibm.com Acked-by: Felipe Balbi felipe.balbi@linux.intel.com Signed-off-by: Arnd Bergmann arnd@arndb.de --- 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(-)
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 8c1b63a4337b..5de0796f2786 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -1221,34 +1221,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<n>_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 3ce837e4b24c..21ee5751c04e 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -45,10 +45,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"); @@ -72,9 +68,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, }; @@ -228,7 +222,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); @@ -1232,25 +1225,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 20413c276c61..addc210d198a 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1347,14 +1347,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,
@@ -1363,9 +1355,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, };
On Tue, Apr 16, 2019 at 10:19:48PM +0200, Arnd Bergmann wrote:
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.
Acked-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Acked-by: Andrew Donnellan andrew.donnellan@au1.ibm.com Acked-by: Felipe Balbi felipe.balbi@linux.intel.com Signed-off-by: Arnd Bergmann arnd@arndb.de
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 +-----------
ACK, provided that all their ioctls are taking pointers (which is worth mentioning in commit message, assuming it's true)
The ceph_ioctl function is used both for files and directories, but only the files support doing that in 32-bit compat mode.
For consistency, add the same compat handler to the dir operations as well.
Reviewed-by: "Yan, Zheng" zyan@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/ceph/dir.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index a8f429882249..7c060cb22aa3 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1785,6 +1785,7 @@ const struct file_operations ceph_dir_fops = { .open = ceph_open, .release = ceph_release, .unlocked_ioctl = ceph_ioctl, + .compat_ioctl = ceph_ioctl, .fsync = ceph_fsync, .lock = ceph_lock, .flock = ceph_flock,
On Tue, Apr 16, 2019 at 10:19:49PM +0200, Arnd Bergmann wrote:
The ceph_ioctl function is used both for files and directories, but only the files support doing that in 32-bit compat mode.
For consistency, add the same compat handler to the dir operations as well.
Reviewed-by: "Yan, Zheng" zyan@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann arnd@arndb.de
fs/ceph/dir.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index a8f429882249..7c060cb22aa3 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1785,6 +1785,7 @@ const struct file_operations ceph_dir_fops = { .open = ceph_open, .release = ceph_release, .unlocked_ioctl = ceph_ioctl,
- .compat_ioctl = ceph_ioctl,
Again, broken on s390 (and so's the ceph_file_ops, of course). It wants compat_ptr() applied to argument...
On Wed, Apr 17, 2019 at 11:23 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Tue, Apr 16, 2019 at 10:19:49PM +0200, Arnd Bergmann wrote:
The ceph_ioctl function is used both for files and directories, but only the files support doing that in 32-bit compat mode.
For consistency, add the same compat handler to the dir operations as well.
Reviewed-by: "Yan, Zheng" zyan@redhat.com Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann arnd@arndb.de
fs/ceph/dir.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index a8f429882249..7c060cb22aa3 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1785,6 +1785,7 @@ const struct file_operations ceph_dir_fops = { .open = ceph_open, .release = ceph_release, .unlocked_ioctl = ceph_ioctl,
.compat_ioctl = ceph_ioctl,
Again, broken on s390 (and so's the ceph_file_ops, of course). It wants compat_ptr() applied to argument...
This gets changed in a later patch, I intentionally left this one doing the same as ceph_file_fops so the patch can be backported if necessary, without also backporting the patch that adds compat_ptr_ioctl.
Arnd
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 ever 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 jgg@mellanox.com Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Acked-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Acked-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Acked-by: David Sterba dsterba@suse.com Acked-by: Darren Hart (VMware) dvhart@infradead.org Acked-by: Jonathan Cameron Jonathan.Cameron@huawei.com Acked-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Arnd Bergmann arnd@arndb.de --- 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/mfd/cros_ec_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/ceph/dir.c | 2 +- fs/ceph/file.c | 2 +- fs/fuse/dev.c | 2 +- fs/notify/fanotify/fanotify_user.c | 2 +- fs/userfaultfd.c | 2 +- net/rfkill/core.c | 2 +- 36 files changed, 39 insertions(+), 57 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 4b9c7ca492e6..48109ade7234 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -5998,7 +5998,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 7c858020d14b..0cb336fe6324 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -325,9 +325,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, };
/* diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 32dcf7b4c935..411de6a8a0ad 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -419,5 +419,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 4f6305ca52c8..0949f91eb85f 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -488,5 +488,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 083bd8114db1..5d6ac7885aa7 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 9fc51eff1079..e7284d38b66d 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -476,9 +476,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 4700fd5d8c90..eed1bea257b4 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1635,7 +1635,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 70b7d80431a9..ac4321d7c800 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -1120,7 +1120,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 = { @@ -1131,7 +1131,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 struct ib_client uverbs_client = { diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index f862f1b7f996..9ccc7e9cbc8e 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -730,9 +730,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/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index d275deaecb12..4a602a40d75c 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -251,9 +251,7 @@ static const struct file_operations fops = { .release = ec_device_release, .read = ec_device_read, .unlocked_ioctl = ec_device_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ec_device_ioctl, -#endif + .compat_ioctl = compat_ptr_ioctl, };
static void cros_ec_class_release(struct device *dev) diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index 997f92543dd4..5bb406dabe85 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -969,7 +969,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 7bbff0af29b2..065ebd584482 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -1167,7 +1167,7 @@ static const struct file_operations nvdimm_bus_fops = { .owner = THIS_MODULE, .open = nd_open, .unlocked_ioctl = nd_ioctl, - .compat_ioctl = nd_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, };
@@ -1175,7 +1175,7 @@ static const struct file_operations nvdimm_fops = { .owner = THIS_MODULE, .open = nd_open, .unlocked_ioctl = nvdimm_ioctl, - .compat_ioctl = nvdimm_ioctl, + .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, };
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 2c43e12b70af..560929bee5ce 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2739,7 +2739,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 e22766c79fe9..3a54b4b616e2 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -1006,7 +1006,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 7b26b6ccf1a0..dded9cef42f4 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -889,7 +889,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 a36e4cf1841d..c9f60656f54d 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -155,7 +155,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 1a6e7224017c..dd2dfa85fc68 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -714,9 +714,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 7096810fd222..e13d5de1d76e 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -3589,7 +3589,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 e338d7a4f571..c0a1a1218c56 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3988,9 +3988,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 92c2914239e3..1663c163edca 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -567,9 +567,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 17c64fccbb10..eb97acf09868 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -684,7 +684,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 9e9caff905d5..d48c032580d0 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -724,7 +724,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 4942122b2346..bbd0308b13f5 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2220,9 +2220,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 8ba726e600e9..fbf02bf60f62 100644 --- a/drivers/virt/fsl_hypervisor.c +++ b/drivers/virt/fsl_hypervisor.c @@ -703,7 +703,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 120e4340792a..162ea4b6b417 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2307,7 +2307,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/ceph/dir.c b/fs/ceph/dir.c index 7c060cb22aa3..a493b957713f 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1785,7 +1785,7 @@ const struct file_operations ceph_dir_fops = { .open = ceph_open, .release = ceph_release, .unlocked_ioctl = ceph_ioctl, - .compat_ioctl = ceph_ioctl, + .compat_ioctl = compat_ptr_ioctl, .fsync = ceph_fsync, .lock = ceph_lock, .flock = ceph_flock, diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 9f53c3d99304..9b5fe7eee3c1 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -2112,7 +2112,7 @@ const struct file_operations ceph_file_fops = { .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, .unlocked_ioctl = ceph_ioctl, - .compat_ioctl = ceph_ioctl, + .compat_ioctl = compat_ptr_ioctl, .fallocate = ceph_fallocate, .copy_file_range = ceph_copy_file_range, }; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 9971a35cf1ef..dcdb26068b71 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2354,7 +2354,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 a90bb19dcfa2..a55aa029a308 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 89800fc7dc9d..f93dcf8c996f 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1901,7 +1901,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 abca57040f37..3b2f6ea44397 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -1323,7 +1323,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, };
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.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/ide/ide-tape.c | 31 ++++++++++++---- drivers/s390/char/tape_char.c | 41 ++++++++------------ drivers/scsi/osst.c | 34 ++++++++++------- drivers/scsi/st.c | 35 +++++++++++------- fs/compat_ioctl.c | 70 ----------------------------------- include/linux/mtio.h | 58 +++++++++++++++++++++++++++++ 6 files changed, 137 insertions(+), 132 deletions(-) create mode 100644 include/linux/mtio.h
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index db1a65f4b490..54560ae5c054 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -19,6 +19,7 @@
#define IDETAPE_VERSION "1.20"
+#include <linux/compat.h> #include <linux/module.h> #include <linux/types.h> #include <linux/string.h> @@ -1368,7 +1369,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count) * ide-tape ioctls are supported on both interfaces. */ static long do_idetape_chrdev_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg, bool compat) { struct ide_tape_obj *tape = file->private_data; ide_drive_t *drive = tape->drive; @@ -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, compat); 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, compat); default: if (tape->chrdev_dir == IDETAPE_DIR_READ) ide_tape_discard_merge_buffer(drive, 1); @@ -1427,7 +1424,23 @@ static long idetape_chrdev_ioctl(struct file *file, { long ret; mutex_lock(&ide_tape_mutex); - ret = do_idetape_chrdev_ioctl(file, cmd, arg); + ret = do_idetape_chrdev_ioctl(file, cmd, arg, false); + mutex_unlock(&ide_tape_mutex); + 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, true); mutex_unlock(&ide_tape_mutex); return ret; } @@ -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 fc206c9d1c56..522ca9b836e3 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, bool compat) { 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, compat); } 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, compat); } /* 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, false); 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), false); + mutex_unlock(&device->mutex); + return rc; } #endif /* CONFIG_COMPAT */
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index be3c73ebbfde..edfde6edfc18 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -33,6 +33,7 @@ static const char * osst_version = "0.99.4";
#include <linux/module.h>
+#include <linux/compat.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/sched/signal.h> @@ -4941,7 +4942,7 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp) static long osst_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg) { - int i, cmd_nr, cmd_type, blk, retval = 0; + int i, cmd_nr, cmd_type, cmd_size, blk, retval = 0; struct st_modedef * STm; struct st_partstat * STps; struct osst_request * SRpnt = NULL; @@ -4978,6 +4979,7 @@ static long osst_ioctl(struct file * file,
cmd_type = _IOC_TYPE(cmd_in); cmd_nr = _IOC_NR(cmd_in); + cmd_size = _IOC_SIZE(cmd_in); #if DEBUG printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name, cmd_type, cmd_nr, STp->raw?"raw":"normal"); @@ -5179,7 +5181,8 @@ static long osst_ioctl(struct file * file, if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) { struct mtget mt_status;
- if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) { + if (cmd_size != sizeof(struct mtget) && + cmd_size != sizeof(struct mtget32)) { retval = (-EINVAL); goto out; } @@ -5229,21 +5232,18 @@ static long osst_ioctl(struct file * file, STp->drv_buffer != 0) mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
- i = copy_to_user(p, &mt_status, sizeof(struct mtget)); - if (i) { - retval = (-EFAULT); - goto out; - } - - STp->recover_erreg = 0; /* Clear after read */ - retval = 0; + retval = put_user_mtget(p, &mt_status, + cmd_size == sizeof(struct mtget32)); + if (!retval) + STp->recover_erreg = 0; /* Clear after read */ goto out; } /* End of MTIOCGET */
if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) { struct mtpos mt_pos;
- if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) { + if (cmd_size != sizeof(struct mtpos) && + cmd_size != sizeof(struct mtpos32)) { retval = (-EINVAL); goto out; } @@ -5256,9 +5256,7 @@ static long osst_ioctl(struct file * file, 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, cmd_size == sizeof(struct mtpos32)); goto out; } if (SRpnt) osst_release_request(SRpnt); @@ -5284,6 +5282,14 @@ static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned struct osst_tape *STp = file->private_data; struct scsi_device *sdev = STp->device; int ret = -ENOIOCTLCMD; + + switch (cmd_in) { + case MTIOCTOP: + case MTIOCPOS32: + case MTIOCGET32: + return osst_ioctl(file, cmd_in, (unsigned long)compat_ptr(arg)); + } + if (sdev->host->hostt->compat_ioctl) {
ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 19c022e66d63..f0cb35964a30 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -21,6 +21,7 @@ static const char *verstr = "20160209";
#include <linux/module.h>
+#include <linux/compat.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/sched/signal.h> @@ -3502,7 +3503,7 @@ static int partition_tape(struct scsi_tape *STp, int size) /* The ioctl command */ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) { - int i, cmd_nr, cmd_type, bt; + int i, cmd_nr, cmd_type, cmd_size, bt; int retval = 0; unsigned int blk; struct scsi_tape *STp = file->private_data; @@ -3536,6 +3537,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
cmd_type = _IOC_TYPE(cmd_in); cmd_nr = _IOC_NR(cmd_in); + cmd_size = _IOC_SIZE(cmd_in);
if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) { struct mtop mtc; @@ -3745,7 +3747,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) { struct mtget mt_status;
- if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) { + if (cmd_size != sizeof(struct mtget) && + cmd_size != sizeof(struct mtget32)) { retval = (-EINVAL); goto out; } @@ -3800,19 +3803,16 @@ 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); - goto out; - } + retval = put_user_mtget(p, &mt_status, + cmd_size == sizeof(struct mtget32));
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)) { struct mtpos mt_pos; - if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) { + if (cmd_size != sizeof(struct mtpos) && + cmd_size != sizeof(struct mtpos32)) { retval = (-EINVAL); goto out; } @@ -3821,9 +3821,8 @@ 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, + cmd_size == sizeof(struct mtpos32)); goto out; } mutex_unlock(&STp->lock); @@ -3857,14 +3856,22 @@ 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) { struct scsi_tape *STp = file->private_data; struct scsi_device *sdev = STp->device; int ret = -ENOIOCTLCMD; + + switch (cmd_in) { + case MTIOCTOP: + case MTIOCPOS32: + case MTIOCGET32: + return st_ioctl(file, cmd_in, (unsigned long)compat_ptr(arg)); + } + 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 ab2ff530313b..6eb7a3f51702 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -27,7 +27,6 @@ #include <linux/file.h> #include <linux/ppp-ioctl.h> #include <linux/if_pppox.h> -#include <linux/mtio.h> #include <linux/tty.h> #include <linux/vt_kern.h> #include <linux/raw.h> @@ -279,70 +278,6 @@ static int sg_grt_trans(struct file *file, return err; }
-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 */ @@ -443,8 +378,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) /* Socket level stuff */ COMPATIBLE_IOCTL(FIOQSIZE) #ifdef CONFIG_BLOCK @@ -775,9 +708,6 @@ static long do_ioctl_trans(unsigned int cmd, return sg_ioctl_trans(file, cmd, compat_ptr(arg)); case SG_GET_REQUEST_TABLE: return sg_grt_trans(file, cmd, compat_ptr(arg)); - case MTIOCGET32: - case MTIOCPOS32: - return mt_ioctl_trans(file, cmd, compat_ptr(arg)); #endif }
diff --git a/include/linux/mtio.h b/include/linux/mtio.h new file mode 100644 index 000000000000..02640756a40d --- /dev/null +++ b/include/linux/mtio.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_MTIO_COMPAT_H +#define _LINUX_MTIO_COMPAT_H + +#include <uapi/linux/mtio.h> +#include <linux/uaccess.h> + +/* + * helper functions for implementing compat ioctls on the four tape + * drivers: we define the 32-bit layout of each incompatible strucucture, + * 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, bool compat) +{ + struct mtget32 k32 = { + .mt_type = k->mt_type, + .mt_resid = k->mt_resid, + .mt_dsreg = k->mt_dsreg, + .mt_gstat = k->mt_gstat, + .mt_fileno = k->mt_fileno, + .mt_blkno = k->mt_blkno, + }; + int ret; + + if (IS_ENABLED(CONFIG_COMPAT) && compat) + 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, bool compat) +{ + if (IS_ENABLED(CONFIG_COMPAT) && compat) + return put_user(k->mt_blkno, (u32 __user *)u); + else + return put_user(k->mt_blkno, (long __user *)u); +} + +#endif
These are two obscure ioctl commands, in a driver that only has compatible commands, so just let the driver handle this itself.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/video/fbdev/aty/atyfb_base.c | 12 +++++++++++- fs/compat_ioctl.c | 2 -- 2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index b6fe103df145..1bc4b6672fdc 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -48,7 +48,7 @@
******************************************************************************/
- +#include <linux/compat.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> @@ -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 6eb7a3f51702..a0f230650de2 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -637,8 +637,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)
On Tue, Apr 16, 2019 at 10:25:35PM +0200, Arnd Bergmann wrote:
+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
Huh? Why isn't that using compat_ioctl_ptr()?
On Wed, Apr 17, 2019 at 10:27:00PM +0100, Al Viro wrote:
On Tue, Apr 16, 2019 at 10:25:35PM +0200, Arnd Bergmann wrote:
+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
Huh? Why isn't that using compat_ioctl_ptr()?
Oh, I see... Nevermind, then.
On 04/16/2019 10:25 PM, Arnd Bergmann wrote:
These are two obscure ioctl commands, in a driver that only has compatible commands, so just let the driver handle this itself.
Signed-off-by: Arnd Bergmann arnd@arndb.de
Acked-by: Bartlomiej Zolnierkiewicz b.zolnierkie@samsung.com
Best regards, -- Bartlomiej Zolnierkiewicz Samsung R&D Institute Poland Samsung Electronics
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.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/isdn/capi/capi.c | 31 +++++++++++++++++++++++++++++++ fs/compat_ioctl.c | 17 ----------------- 2 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index e1da70a9530c..744cfdeb9ecf 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -942,6 +942,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 { + unsigned long 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; @@ -988,6 +1016,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 a0f230650de2..aad7071eaee0 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -44,9 +44,6 @@ #include <net/bluetooth/hci_sock.h> #include <net/bluetooth/rfcomm.h>
-#include <linux/capi.h> -#include <linux/gigaset_dev.h> - #ifdef CONFIG_BLOCK #include <linux/cdrom.h> #include <linux/fd.h> @@ -622,20 +619,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)
All these ioctl commands are compatible, so we can handle them with a trivial wrapper in rfcomm/sock.c and remove the listing in fs/compat_ioctl.c.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 6 ------ net/bluetooth/rfcomm/sock.c | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index aad7071eaee0..efe3df389150 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -42,7 +42,6 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_sock.h> -#include <net/bluetooth/rfcomm.h>
#ifdef CONFIG_BLOCK #include <linux/cdrom.h> @@ -614,11 +613,6 @@ COMPATIBLE_IOCTL(HCIUARTGETPROTO) COMPATIBLE_IOCTL(HCIUARTGETDEVICE) COMPATIBLE_IOCTL(HCIUARTSETFLAGS) COMPATIBLE_IOCTL(HCIUARTGETFLAGS) -COMPATIBLE_IOCTL(RFCOMMCREATEDEV) -COMPATIBLE_IOCTL(RFCOMMRELEASEDEV) -COMPATIBLE_IOCTL(RFCOMMGETDEVLIST) -COMPATIBLE_IOCTL(RFCOMMGETDEVINFO) -COMPATIBLE_IOCTL(RFCOMMSTEALDLC) /* Misc. */ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 90bb53aa4bee..b4eaf21360ef 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -24,7 +24,7 @@ /* * RFCOMM sockets. */ - +#include <linux/compat.h> #include <linux/export.h> #include <linux/debugfs.h> #include <linux/sched/signal.h> @@ -909,6 +909,13 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon return err; }
+#ifdef CONFIG_COMPAT +static int rfcomm_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + return rfcomm_sock_ioctl(sock, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + static int rfcomm_sock_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; @@ -1042,7 +1049,10 @@ static const struct proto_ops rfcomm_sock_ops = { .gettstamp = sock_gettstamp, .poll = bt_sock_poll, .socketpair = sock_no_socketpair, - .mmap = sock_no_mmap + .mmap = sock_no_mmap, +#ifdef CONFIG_COMPAT + .compat_ioctl = rfcomm_sock_compat_ioctl, +#endif };
static const struct net_proto_family rfcomm_sock_family_ops = {
All these ioctl commands are compatible, so we can handle them with a trivial wrapper in hci_sock.c and remove the listing in fs/compat_ioctl.c.
A few of the commands pass integer arguments instead of pointers, so for correctness skip the compat_ptr() conversion here.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 24 ------------------------ net/bluetooth/hci_sock.c | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 25 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index efe3df389150..9024cae05eda 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -40,9 +40,6 @@
#include "internal.h"
-#include <net/bluetooth/bluetooth.h> -#include <net/bluetooth/hci_sock.h> - #ifdef CONFIG_BLOCK #include <linux/cdrom.h> #include <linux/fd.h> @@ -587,27 +584,6 @@ COMPATIBLE_IOCTL(RNDADDENTROPY) COMPATIBLE_IOCTL(RNDZAPENTCNT) COMPATIBLE_IOCTL(RNDCLEARPOOL) /* Bluetooth */ -COMPATIBLE_IOCTL(HCIDEVUP) -COMPATIBLE_IOCTL(HCIDEVDOWN) -COMPATIBLE_IOCTL(HCIDEVRESET) -COMPATIBLE_IOCTL(HCIDEVRESTAT) -COMPATIBLE_IOCTL(HCIGETDEVLIST) -COMPATIBLE_IOCTL(HCIGETDEVINFO) -COMPATIBLE_IOCTL(HCIGETCONNLIST) -COMPATIBLE_IOCTL(HCIGETCONNINFO) -COMPATIBLE_IOCTL(HCIGETAUTHINFO) -COMPATIBLE_IOCTL(HCISETRAW) -COMPATIBLE_IOCTL(HCISETSCAN) -COMPATIBLE_IOCTL(HCISETAUTH) -COMPATIBLE_IOCTL(HCISETENCRYPT) -COMPATIBLE_IOCTL(HCISETPTYPE) -COMPATIBLE_IOCTL(HCISETLINKPOL) -COMPATIBLE_IOCTL(HCISETLINKMODE) -COMPATIBLE_IOCTL(HCISETACLMTU) -COMPATIBLE_IOCTL(HCISETSCOMTU) -COMPATIBLE_IOCTL(HCIBLOCKADDR) -COMPATIBLE_IOCTL(HCIUNBLOCKADDR) -COMPATIBLE_IOCTL(HCIINQUIRY) COMPATIBLE_IOCTL(HCIUARTSETPROTO) COMPATIBLE_IOCTL(HCIUARTGETPROTO) COMPATIBLE_IOCTL(HCIUARTGETDEVICE) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index d32077b28433..5d0ed28c0d3a 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -23,7 +23,7 @@ */
/* Bluetooth HCI sockets. */ - +#include <linux/compat.h> #include <linux/export.h> #include <linux/utsname.h> #include <linux/sched.h> @@ -1054,6 +1054,22 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, return err; }
+#ifdef CONFIG_COMPAT +static int hci_sock_compat_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case HCIDEVUP: + case HCIDEVDOWN: + case HCIDEVRESET: + case HCIDEVRESTAT: + return hci_sock_ioctl(sock, cmd, arg); + } + + return hci_sock_ioctl(sock, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) { @@ -1974,6 +1990,9 @@ static const struct proto_ops hci_sock_ops = { .sendmsg = hci_sock_sendmsg, .recvmsg = hci_sock_recvmsg, .ioctl = hci_sock_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = hci_sock_compat_ioctl, +#endif .poll = datagram_poll, .listen = sock_no_listen, .shutdown = sock_no_shutdown,
As of commit f0193d3ea73b ("change semantics of ldisc ->compat_ioctl()"), all hciuart ioctl commands are handled correctly in the driver, and we never need to go through the table here.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 13 ------------- 1 file changed, 13 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 9024cae05eda..9e96b8b63578 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -273,13 +273,6 @@ static int sg_grt_trans(struct file *file,
#endif /* CONFIG_BLOCK */
-/* Bluetooth ioctls */ -#define HCIUARTSETPROTO _IOW('U', 200, int) -#define HCIUARTGETPROTO _IOR('U', 201, int) -#define HCIUARTGETDEVICE _IOR('U', 202, int) -#define HCIUARTSETFLAGS _IOW('U', 203, int) -#define HCIUARTGETFLAGS _IOR('U', 204, int) - /* on ia32 l_start is on a 32-bit boundary */ #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) struct space_resv_32 { @@ -583,12 +576,6 @@ COMPATIBLE_IOCTL(RNDGETPOOL) COMPATIBLE_IOCTL(RNDADDENTROPY) COMPATIBLE_IOCTL(RNDZAPENTCNT) COMPATIBLE_IOCTL(RNDCLEARPOOL) -/* Bluetooth */ -COMPATIBLE_IOCTL(HCIUARTSETPROTO) -COMPATIBLE_IOCTL(HCIUARTGETPROTO) -COMPATIBLE_IOCTL(HCIUARTGETDEVICE) -COMPATIBLE_IOCTL(HCIUARTSETFLAGS) -COMPATIBLE_IOCTL(HCIUARTGETFLAGS) /* Misc. */ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO)
The two drivers implementing these both gained proper compat_ioctl() handlers a long time ago with commits bb6c8d8fa9b5 ("HID: hiddev: Add 32bit ioctl compatibilty") and ae5e49c79c05 ("HID: hidraw: add compatibility ioctl() for 32-bit applications."), so the lists in fs/compat_ioctl.c are no longer used.
It appears that the lists were also incomplete, so the translation didn't actually work correctly when it was still in use.
Remove them as cleanup.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 17 ----------------- 1 file changed, 17 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 9e96b8b63578..5d13336e9eaa 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -581,23 +581,6 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* hiddev */ -COMPATIBLE_IOCTL(HIDIOCGVERSION) -COMPATIBLE_IOCTL(HIDIOCAPPLICATION) -COMPATIBLE_IOCTL(HIDIOCGDEVINFO) -COMPATIBLE_IOCTL(HIDIOCGSTRING) -COMPATIBLE_IOCTL(HIDIOCINITREPORT) -COMPATIBLE_IOCTL(HIDIOCGREPORT) -COMPATIBLE_IOCTL(HIDIOCSREPORT) -COMPATIBLE_IOCTL(HIDIOCGREPORTINFO) -COMPATIBLE_IOCTL(HIDIOCGFIELDINFO) -COMPATIBLE_IOCTL(HIDIOCGUSAGE) -COMPATIBLE_IOCTL(HIDIOCSUSAGE) -COMPATIBLE_IOCTL(HIDIOCGUCODE) -COMPATIBLE_IOCTL(HIDIOCGFLAG) -COMPATIBLE_IOCTL(HIDIOCSFLAG) -COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX) -COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO) /* joystick */ COMPATIBLE_IOCTL(JSIOCGVERSION) COMPATIBLE_IOCTL(JSIOCGAXES)
Em Tue, 16 Apr 2019 22:25:33 +0200 Arnd Bergmann arnd@arndb.de escreveu:
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 ever 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 jgg@mellanox.com Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Acked-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org Acked-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Acked-by: David Sterba dsterba@suse.com Acked-by: Darren Hart (VMware) dvhart@infradead.org Acked-by: Jonathan Cameron Jonathan.Cameron@huawei.com Acked-by: Bjorn Andersson bjorn.andersson@linaro.org Signed-off-by: Arnd Bergmann arnd@arndb.de
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 +---
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
In thesis, nothing prevents to use LIRC API on s390 - as this isn't a driver but, instead, RC core feature to expose raw remote controller codes to userspace.
Yet, lirc_dev will only work if the system has a remote controller driver.
Well, we don't have any for s390. Despite we don't have such driver, I can't possible see why someone would use a remote controller for a mainframe :-p
Anyway, if someone ever come with such driver/usecase, reverting this change (or adding an #ifdef to check if arch is 390) should be pretty straight forward.
So:
Acked-by: Mauro Carvalho Chehab mchehab+samsung@kernel.org
drivers/mfd/cros_ec_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/ceph/dir.c | 2 +- fs/ceph/file.c | 2 +- fs/fuse/dev.c | 2 +- fs/notify/fanotify/fanotify_user.c | 2 +- fs/userfaultfd.c | 2 +- net/rfkill/core.c | 2 +- 36 files changed, 39 insertions(+), 57 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 4b9c7ca492e6..48109ade7234 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -5998,7 +5998,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 7c858020d14b..0cb336fe6324 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -325,9 +325,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,
}; /* diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 32dcf7b4c935..411de6a8a0ad 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -419,5 +419,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 4f6305ca52c8..0949f91eb85f 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -488,5 +488,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 083bd8114db1..5d6ac7885aa7 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 9fc51eff1079..e7284d38b66d 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -476,9 +476,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 4700fd5d8c90..eed1bea257b4 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1635,7 +1635,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 70b7d80431a9..ac4321d7c800 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -1120,7 +1120,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 = { @@ -1131,7 +1131,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 struct ib_client uverbs_client = { diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index f862f1b7f996..9ccc7e9cbc8e 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -730,9 +730,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/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index d275deaecb12..4a602a40d75c 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -251,9 +251,7 @@ static const struct file_operations fops = { .release = ec_device_release, .read = ec_device_read, .unlocked_ioctl = ec_device_ioctl, -#ifdef CONFIG_COMPAT
- .compat_ioctl = ec_device_ioctl,
-#endif
- .compat_ioctl = compat_ptr_ioctl,
}; static void cros_ec_class_release(struct device *dev) diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index 997f92543dd4..5bb406dabe85 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -969,7 +969,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 7bbff0af29b2..065ebd584482 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -1167,7 +1167,7 @@ static const struct file_operations nvdimm_bus_fops = { .owner = THIS_MODULE, .open = nd_open, .unlocked_ioctl = nd_ioctl,
- .compat_ioctl = nd_ioctl,
- .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek,
}; @@ -1175,7 +1175,7 @@ static const struct file_operations nvdimm_fops = { .owner = THIS_MODULE, .open = nd_open, .unlocked_ioctl = nvdimm_ioctl,
- .compat_ioctl = nvdimm_ioctl,
- .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek,
}; diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 2c43e12b70af..560929bee5ce 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2739,7 +2739,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 e22766c79fe9..3a54b4b616e2 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -1006,7 +1006,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 7b26b6ccf1a0..dded9cef42f4 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -889,7 +889,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 a36e4cf1841d..c9f60656f54d 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -155,7 +155,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 1a6e7224017c..dd2dfa85fc68 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -714,9 +714,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 7096810fd222..e13d5de1d76e 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -3589,7 +3589,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 e338d7a4f571..c0a1a1218c56 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -3988,9 +3988,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 92c2914239e3..1663c163edca 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -567,9 +567,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 17c64fccbb10..eb97acf09868 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -684,7 +684,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 9e9caff905d5..d48c032580d0 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -724,7 +724,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 4942122b2346..bbd0308b13f5 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -2220,9 +2220,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 8ba726e600e9..fbf02bf60f62 100644 --- a/drivers/virt/fsl_hypervisor.c +++ b/drivers/virt/fsl_hypervisor.c @@ -703,7 +703,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 120e4340792a..162ea4b6b417 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2307,7 +2307,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/ceph/dir.c b/fs/ceph/dir.c index 7c060cb22aa3..a493b957713f 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1785,7 +1785,7 @@ const struct file_operations ceph_dir_fops = { .open = ceph_open, .release = ceph_release, .unlocked_ioctl = ceph_ioctl,
- .compat_ioctl = ceph_ioctl,
- .compat_ioctl = compat_ptr_ioctl, .fsync = ceph_fsync, .lock = ceph_lock, .flock = ceph_flock,
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 9f53c3d99304..9b5fe7eee3c1 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -2112,7 +2112,7 @@ const struct file_operations ceph_file_fops = { .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, .unlocked_ioctl = ceph_ioctl,
- .compat_ioctl = ceph_ioctl,
- .compat_ioctl = compat_ptr_ioctl, .fallocate = ceph_fallocate, .copy_file_range = ceph_copy_file_range,
}; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 9971a35cf1ef..dcdb26068b71 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2354,7 +2354,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 a90bb19dcfa2..a55aa029a308 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 89800fc7dc9d..f93dcf8c996f 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1901,7 +1901,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 abca57040f37..3b2f6ea44397 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -1323,7 +1323,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, };
Thanks, Mauro
On Thu, Apr 25, 2019 at 5:22 PM Mauro Carvalho Chehab mchehab+samsung@kernel.org wrote:
Em Tue, 16 Apr 2019 22:25:33 +0200 Arnd Bergmann arnd@arndb.de escreveu:
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
No, the purpose of compat_ptr_ioctl() is to make sure it works everywhere including s390.
Even on s390 it tends to work most of the time, but for correctness the upper bit of a 32-bit pointer needs to be cleared, as compat_ptr_ioctl does, in case some application passes a pointer with that bit set. [IIRC, in the instruction pointer, the high bit is set, in data references it is ignored but usually cleared, but it may be left on for IP-relative address generation]
Arnd
On Thu, Apr 25, 2019 at 12:21:53PM -0300, Mauro Carvalho Chehab wrote:
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
No; s390 is where "oh, just set ->compat_ioctl same as ->unlocked_ioctl and be done with that; compat_ptr() is a no-op anyway" breaks. IOW, s390 is the reason for having compat_ptr_ioctl() in the first place; that thing works on all biarch architectures, as long as all stuff handled by ->ioctl() takes pointer to arch-independent object as argument. IOW, argument ignored => OK any arithmetical type => no go, compat_ptr() would bugger it pointer to int => OK pointer to string => OK pointer to u64 => OK pointer to struct {u64 addr; char s[11];} => OK pointer to long => needs explicit handler pointer to struct {void *addr; char s[11];} => needs explicit handler pointer to struct {int x; u64 y;} => needs explicit handler on amd64 For "just use ->unlocked_ioctl for ->ioctl" we have argument ignored => OK any arithmetical type => OK any pointer => instant breakage on s390, in addtion to cases that break with compat_ptr_ioctl().
Probably some form of that ought to go into commit message for compat_ptr_ioctl() introduction...
Em Thu, 25 Apr 2019 16:35:34 +0100 Al Viro viro@zeniv.linux.org.uk escreveu:
On Thu, Apr 25, 2019 at 12:21:53PM -0300, Mauro Carvalho Chehab wrote:
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
No; s390 is where "oh, just set ->compat_ioctl same as ->unlocked_ioctl and be done with that; compat_ptr() is a no-op anyway" breaks. IOW, s390 is the reason for having compat_ptr_ioctl() in the first place; that thing works on all biarch architectures, as long as all stuff handled by ->ioctl() takes pointer to arch-independent object as argument. IOW, argument ignored => OK any arithmetical type => no go, compat_ptr() would bugger it pointer to int => OK
That's the case for all LIRC ioctls: they all use a pointer to u32 argument.
pointer to string => OK pointer to u64 => OK pointer to struct {u64 addr; char s[11];} => OK pointer to long => needs explicit handler pointer to struct {void *addr; char s[11];} => needs explicit handler pointer to struct {int x; u64 y;} => needs explicit handler on amd64 For "just use ->unlocked_ioctl for ->ioctl" we have argument ignored => OK any arithmetical type => OK any pointer => instant breakage on s390, in addtion to cases that break with compat_ptr_ioctl().
Probably some form of that ought to go into commit message for compat_ptr_ioctl() introduction...
Agreed.
Thanks, Mauro
On Thu, Apr 25, 2019 at 5:35 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Thu, Apr 25, 2019 at 12:21:53PM -0300, Mauro Carvalho Chehab wrote:
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
No; s390 is where "oh, just set ->compat_ioctl same as ->unlocked_ioctl and be done with that; compat_ptr() is a no-op anyway" breaks. IOW, s390 is the reason for having compat_ptr_ioctl() in the first place; that thing works on all biarch architectures, as long as all stuff handled by ->ioctl() takes pointer to arch-independent object as argument. IOW, argument ignored => OK any arithmetical type => no go, compat_ptr() would bugger it pointer to int => OK pointer to string => OK pointer to u64 => OK pointer to struct {u64 addr; char s[11];} => OK
To be extra pedantic, the 'struct {u64 addr; char s[11];} ' case is also broken on x86, because sizeof (obj) is smaller on i386, even though the location of the members are the same. i.e. you can copy_from_user() this, but not copy_to_user(), which overwrites 4 bytes after the end of the 20-byte user structure.
Arnd
On Thu, Apr 25, 2019 at 05:55:23PM +0200, Arnd Bergmann wrote:
On Thu, Apr 25, 2019 at 5:35 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Thu, Apr 25, 2019 at 12:21:53PM -0300, Mauro Carvalho Chehab wrote:
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
No; s390 is where "oh, just set ->compat_ioctl same as ->unlocked_ioctl and be done with that; compat_ptr() is a no-op anyway" breaks. IOW, s390 is the reason for having compat_ptr_ioctl() in the first place; that thing works on all biarch architectures, as long as all stuff handled by ->ioctl() takes pointer to arch-independent object as argument. IOW, argument ignored => OK any arithmetical type => no go, compat_ptr() would bugger it pointer to int => OK pointer to string => OK pointer to u64 => OK pointer to struct {u64 addr; char s[11];} => OK
To be extra pedantic, the 'struct {u64 addr; char s[11];} ' case is also broken on x86, because sizeof (obj) is smaller on i386, even though the location of the members are the same. i.e. you can copy_from_user() this, but not copy_to_user(), which overwrites 4 bytes after the end of the 20-byte user structure.
D'oh! FWIW, it might be worth putting into Documentation/ somewhere; basically, what is and what isn't biarch-neutral.
Or arch-neutral, for that matter - it's very close. The only real exception, IIRC, is an extra twist on m68k, where int behaves like x86 long long - its alignment is only half its size, so sizeof(struct {char c; int x;}) is 6, not 8 as everywhere else. Irrelevant for biarch, thankfully (until somebody gets insane enough to implement 64bit coldfire, kernel port for it *and* biarch support for m68k binaries on that thing, that is)...
On Thu, 2019-04-25 at 17:55 +0200, Arnd Bergmann wrote:
On Thu, Apr 25, 2019 at 5:35 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Thu, Apr 25, 2019 at 12:21:53PM -0300, Mauro Carvalho Chehab wrote:
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
No; s390 is where "oh, just set ->compat_ioctl same as ->unlocked_ioctl and be done with that; compat_ptr() is a no-op anyway" breaks. IOW, s390 is the reason for having compat_ptr_ioctl() in the first place; that thing works on all biarch architectures, as long as all stuff handled by ->ioctl() takes pointer to arch-independent object as argument. IOW, argument ignored => OK any arithmetical type => no go, compat_ptr() would bugger it pointer to int => OK pointer to string => OK pointer to u64 => OK pointer to struct {u64 addr; char s[11];} => OK
To be extra pedantic, the 'struct {u64 addr; char s[11];} ' case is also broken on x86, because sizeof (obj) is smaller on i386, even though the location of the members are the same. i.e. you can copy_from_user() this
Actually, you can't even do that because the struct might sit at the end of a page and then you'd erroneously fault in this case.
We had this a while ago with struct ifreq, see commit 98406133dd and its parents.
johannes
On Thu, Apr 25, 2019 at 11:25 PM Johannes Berg johannes@sipsolutions.net wrote:
On Thu, 2019-04-25 at 17:55 +0200, Arnd Bergmann wrote:
On Thu, Apr 25, 2019 at 5:35 PM Al Viro viro@zeniv.linux.org.uk wrote:
On Thu, Apr 25, 2019 at 12:21:53PM -0300, Mauro Carvalho Chehab wrote:
If I understand your patch description well, using compat_ptr_ioctl only works if the driver is not for s390, right?
No; s390 is where "oh, just set ->compat_ioctl same as ->unlocked_ioctl and be done with that; compat_ptr() is a no-op anyway" breaks. IOW, s390 is the reason for having compat_ptr_ioctl() in the first place; that thing works on all biarch architectures, as long as all stuff handled by ->ioctl() takes pointer to arch-independent object as argument. IOW, argument ignored => OK any arithmetical type => no go, compat_ptr() would bugger it pointer to int => OK pointer to string => OK pointer to u64 => OK pointer to struct {u64 addr; char s[11];} => OK
To be extra pedantic, the 'struct {u64 addr; char s[11];} ' case is also broken on x86, because sizeof (obj) is smaller on i386, even though the location of the members are the same. i.e. you can copy_from_user() this
Actually, you can't even do that because the struct might sit at the end of a page and then you'd erroneously fault in this case.
We had this a while ago with struct ifreq, see commit 98406133dd and its parents.
Yes, you are right. Very rare to hit with real-life code, but easily reproduced by intentionally hitting it and clearly a bug.
As the saying goes
| the difference between "always works" and "almost always works" | is called data corruption
here the difference is an -EFAULT.
Arnd
The SNDCTL_* and SOUND_* commands are the old OSS user interface.
I checked all the sound ioctl commands listed in fs/compat_ioctl.c to see if we still need the translation handlers. Here is what I found:
- sound/oss/ is (almost) gone from the kernel, this is what actually needed all the translations - The ALSA emulation for OSS correctly handles all compat_ioctl commands already. - sound/oss/dmasound/ is the last holdout of the original OSS code, this is only used on arch/m68k, which has no 64-bit mode and hence needs no compat handlers - arch/um/drivers/hostaudio_kern.c may run in 64-bit mode with 32-bit x86 user space underneath it. This rare corner case is the only one that still needs the compat handlers.
By adding a simple redirect of .compat_ioctl to .unlocked_ioctl in the UML driver, we can remove all the COMPATIBLE_IOCTL() annotations without a change in functionality. For completeness, I'm adding the same thing to the dmasound file, knowing that it makes no difference.
The compat_ioctl list contains one comment about SNDCTL_DSP_MAPINBUF and SNDCTL_DSP_MAPOUTBUF, which actually would need a translation handler if implemented. However, the native implementation just returns -EINVAL, so we don't care.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- arch/um/drivers/hostaudio_kern.c | 1 + fs/compat_ioctl.c | 158 ----------------------------- sound/core/oss/pcm_oss.c | 4 + sound/oss/dmasound/dmasound_core.c | 2 + 4 files changed, 7 insertions(+), 158 deletions(-)
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 7f9dbdbc4eb7..1bf139c3727a 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -298,6 +298,7 @@ static const struct file_operations hostaudio_fops = { .write = hostaudio_write, .poll = hostaudio_poll, .unlocked_ioctl = hostaudio_ioctl, + .compat_ioctl = compat_ptr_ioctl, .mmap = NULL, .open = hostaudio_open, .release = hostaudio_release, diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 5d13336e9eaa..625536aa6b03 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -51,8 +51,6 @@ #include <linux/uaccess.h> #include <linux/watchdog.h>
-#include <linux/soundcard.h> - #include <linux/hiddev.h>
@@ -399,162 +397,6 @@ COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) /* PPP stuff */ COMPATIBLE_IOCTL(PPPIOCGUNIT) COMPATIBLE_IOCTL(PPPIOCGCHAN) -/* Big A */ -/* sparc only */ -/* Big Q for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET) -COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE) -COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR) -COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI) -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS) -COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL) -COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC) -COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE) -/* Big T for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE) -COMPATIBLE_IOCTL(SNDCTL_TMR_START) -COMPATIBLE_IOCTL(SNDCTL_TMR_STOP) -COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE) -COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO) -COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE) -COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME) -COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT) -/* Little m for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD) -/* Big P for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_DSP_RESET) -COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC) -COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED) -COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE) -COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER) -COMPATIBLE_IOCTL(SNDCTL_DSP_POST) -COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR) -/* SNDCTL_DSP_MAPINBUF, XXX needs translation */ -/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */ -COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY) -COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER) -/* Big C for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_COPR_RESET) -COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD) -COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_RUN) -COMPATIBLE_IOCTL(SNDCTL_COPR_HALT) -COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG) -/* Big M for sound/OSS */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE) -/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */ -/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE) -/* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */ -/* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS) -COMPATIBLE_IOCTL(SOUND_MIXER_AGC) -COMPATIBLE_IOCTL(SOUND_MIXER_3DSE) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5) -COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS) -COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS) -COMPATIBLE_IOCTL(OSS_GETVERSION) /* Raw devices */ COMPATIBLE_IOCTL(RAW_SETBIND) COMPATIBLE_IOCTL(RAW_GETBIND) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index f6ae68017608..f85ea328fd27 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2732,6 +2732,10 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long static long snd_pcm_oss_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { + /* + * Everything is compatbile except SNDCTL_DSP_MAPINBUF/SNDCTL_DSP_MAPOUTBUF, + * which are not implemented for the native case either + */ return snd_pcm_oss_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); } #else diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index fc9bcd47d6a4..f802ea331e24 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -384,6 +384,7 @@ static const struct file_operations mixer_fops = .owner = THIS_MODULE, .llseek = no_llseek, .unlocked_ioctl = mixer_unlocked_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = mixer_open, .release = mixer_release, }; @@ -1167,6 +1168,7 @@ static const struct file_operations sq_fops = .write = sq_write, .poll = sq_poll, .unlocked_ioctl = sq_unlocked_ioctl, + .compat_ioctl = compat_ptr_ioctl, .open = sq_open, .release = sq_release, };
Since commit 07d106d0a33d ("vfs: fix up ENOIOCTLCMD error handling"), we don't warn about unhandled compat-ioctl command code any more, but just return the same error that a native file descriptor returns when there is no handler.
This means the IGNORE_IOCTL() annotations are completely useless and can all be removed. TIOCSTART/TIOCSTOP and KDGHWCLK/KDSHWCLK fall into the same category, but for some reason were listed as COMPATIBLE_IOCTL().
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 56 ----------------------------------------------- 1 file changed, 56 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 625536aa6b03..bae7b38a881f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -56,11 +56,6 @@
#include <linux/sort.h>
-#ifdef CONFIG_SPARC -#include <linux/fb.h> -#include <asm/fbio.h> -#endif - #define convert_in_user(srcptr, dstptr) \ ({ \ typeof(*srcptr) val; \ @@ -313,17 +308,7 @@ static int compat_ioctl_preallocate(struct file *file, #define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff)
#define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd), -/* ioctl should not be warned about even if it's not implemented. - Valid reasons to use this: - - It is implemented with ->compat_ioctl on some device, but programs - call it on others too. - - The ioctl is not implemented in the native kernel, but programs - call it commonly anyways. - Most other reasons are not valid. */ -#define IGNORE_IOCTL(cmd) COMPATIBLE_IOCTL(cmd) - static unsigned int ioctl_pointer[] = { -/* compatible ioctls first */ /* Little t */ COMPATIBLE_IOCTL(TIOCOUTQ) /* Little f */ @@ -351,25 +336,9 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) #endif -/* Big V (don't complain on serial console) */ -IGNORE_IOCTL(VT_OPENQRY) -IGNORE_IOCTL(VT_GETMODE) -/* - * These two are only for the sbus rtc driver, but - * hwclock tries them on every rtc device first when - * running on sparc. On other architectures the entries - * are useless but harmless. - */ -COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ -COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ /* Socket level stuff */ COMPATIBLE_IOCTL(FIOQSIZE) #ifdef CONFIG_BLOCK -/* md calls this on random blockdevs */ -IGNORE_IOCTL(RAID_VERSION) -/* qemu/qemu-img might call these two on plain files for probing */ -IGNORE_IOCTL(CDROM_DRIVE_STATUS) -IGNORE_IOCTL(FDGETPRM32) /* SG stuff */ COMPATIBLE_IOCTL(SG_SET_TIMEOUT) COMPATIBLE_IOCTL(SG_GET_TIMEOUT) @@ -428,31 +397,6 @@ COMPATIBLE_IOCTL(JSIOCGVERSION) COMPATIBLE_IOCTL(JSIOCGAXES) COMPATIBLE_IOCTL(JSIOCGBUTTONS) COMPATIBLE_IOCTL(JSIOCGNAME(0)) - -/* fat 'r' ioctls. These are handled by fat with ->compat_ioctl, - but we don't want warnings on other file systems. So declare - them as compatible here. */ -#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2]) -#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2]) - -IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32) -IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32) - -#ifdef CONFIG_SPARC -/* Sparc framebuffers, handled in sbusfb_compat_ioctl() */ -IGNORE_IOCTL(FBIOGTYPE) -IGNORE_IOCTL(FBIOSATTR) -IGNORE_IOCTL(FBIOGATTR) -IGNORE_IOCTL(FBIOSVIDEO) -IGNORE_IOCTL(FBIOGVIDEO) -IGNORE_IOCTL(FBIOSCURPOS) -IGNORE_IOCTL(FBIOGCURPOS) -IGNORE_IOCTL(FBIOGCURMAX) -IGNORE_IOCTL(FBIOPUTCMAP32) -IGNORE_IOCTL(FBIOGETCMAP32) -IGNORE_IOCTL(FBIOSCURSOR32) -IGNORE_IOCTL(FBIOGCURSOR32) -#endif };
/*
These are all handled by the random driver, so instead of listing each ioctl, we can just use the same function to deal with both native and compat commands.
Acked-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Arnd Bergmann arnd@arndb.de --- drivers/char/random.c | 1 + fs/compat_ioctl.c | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c index 38c6d1af6d1c..4f397c70d89b 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -2025,6 +2025,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 bae7b38a881f..78144a599f36 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -380,13 +380,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)
The joystick driver already handles these just fine, so the entries in the table are not needed any more.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 7 ------- 1 file changed, 7 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 78144a599f36..c81f5241664e 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -11,8 +11,6 @@ * ioctls. */
-#include <linux/joystick.h> - #include <linux/types.h> #include <linux/compat.h> #include <linux/kernel.h> @@ -385,11 +383,6 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* joystick */ -COMPATIBLE_IOCTL(JSIOCGVERSION) -COMPATIBLE_IOCTL(JSIOCGAXES) -COMPATIBLE_IOCTL(JSIOCGBUTTONS) -COMPATIBLE_IOCTL(JSIOCGNAME(0)) };
/*
The /proc/pci/ implementation already handles these just fine, so the entries in the table are not needed any more.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c81f5241664e..6ad45550b4b1 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -29,7 +29,6 @@ #include <linux/vt_kern.h> #include <linux/raw.h> #include <linux/blkdev.h> -#include <linux/pci.h> #include <linux/serial.h> #include <linux/ctype.h> #include <linux/syscalls.h> @@ -378,11 +377,6 @@ COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT) COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT) COMPATIBLE_IOCTL(WDIOC_SETPRETIMEOUT) COMPATIBLE_IOCTL(WDIOC_GETPRETIMEOUT) -/* Misc. */ -COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) -COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) };
/*
The /dev/rawX implementation already handles these just fine, so the entries in the table are not needed any more.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 6ad45550b4b1..63de00cc85df 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -27,7 +27,6 @@ #include <linux/if_pppox.h> #include <linux/tty.h> #include <linux/vt_kern.h> -#include <linux/raw.h> #include <linux/blkdev.h> #include <linux/serial.h> #include <linux/ctype.h> @@ -363,9 +362,6 @@ COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) /* PPP stuff */ COMPATIBLE_IOCTL(PPPIOCGUNIT) COMPATIBLE_IOCTL(PPPIOCGCHAN) -/* Raw devices */ -COMPATIBLE_IOCTL(RAW_SETBIND) -COMPATIBLE_IOCTL(RAW_GETBIND) /* Watchdog */ COMPATIBLE_IOCTL(WDIOC_GETSUPPORT) COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
Commit aa98aa31987a ("md: move compat_ioctl handling into md.c") already removed the COMPATIBLE_IOCTL() table entries and added a complete implementation, but a few lines got left behind and should also be removed here.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- fs/compat_ioctl.c | 13 ------------- 1 file changed, 13 deletions(-)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 63de00cc85df..09f42e0585b7 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -394,19 +394,6 @@ static long do_ioctl_trans(unsigned int cmd, #endif }
- /* - * These take an integer instead of a pointer as 'arg', - * so we must not do a compat_ptr() translation. - */ - switch (cmd) { - /* RAID */ - case HOT_REMOVE_DISK: - case HOT_ADD_DISK: - case SET_DISK_FAULTY: - case SET_BITMAP_FILE: - return vfs_ioctl(file, cmd, arg); - } - return -ENOIOCTLCMD; }
On Tue, 16 Apr 2019 22:28:05 +0200, Arnd Bergmann wrote:
The SNDCTL_* and SOUND_* commands are the old OSS user interface.
I checked all the sound ioctl commands listed in fs/compat_ioctl.c to see if we still need the translation handlers. Here is what I found:
- sound/oss/ is (almost) gone from the kernel, this is what actually needed all the translations
- The ALSA emulation for OSS correctly handles all compat_ioctl commands already.
- sound/oss/dmasound/ is the last holdout of the original OSS code, this is only used on arch/m68k, which has no 64-bit mode and hence needs no compat handlers
- arch/um/drivers/hostaudio_kern.c may run in 64-bit mode with 32-bit x86 user space underneath it. This rare corner case is the only one that still needs the compat handlers.
By adding a simple redirect of .compat_ioctl to .unlocked_ioctl in the UML driver, we can remove all the COMPATIBLE_IOCTL() annotations without a change in functionality. For completeness, I'm adding the same thing to the dmasound file, knowing that it makes no difference.
The compat_ioctl list contains one comment about SNDCTL_DSP_MAPINBUF and SNDCTL_DSP_MAPOUTBUF, which actually would need a translation handler if implemented. However, the native implementation just returns -EINVAL, so we don't care.
Signed-off-by: Arnd Bergmann arnd@arndb.de
This looks like a really nice cleanup. Thanks!
Reviewed-by: Takashi Iwai tiwai@suse.de
Takashi
On Wed, 17 Apr 2019 10:05:33 +0200, Takashi Iwai wrote:
On Tue, 16 Apr 2019 22:28:05 +0200, Arnd Bergmann wrote:
The SNDCTL_* and SOUND_* commands are the old OSS user interface.
I checked all the sound ioctl commands listed in fs/compat_ioctl.c to see if we still need the translation handlers. Here is what I found:
- sound/oss/ is (almost) gone from the kernel, this is what actually needed all the translations
- The ALSA emulation for OSS correctly handles all compat_ioctl commands already.
- sound/oss/dmasound/ is the last holdout of the original OSS code, this is only used on arch/m68k, which has no 64-bit mode and hence needs no compat handlers
- arch/um/drivers/hostaudio_kern.c may run in 64-bit mode with 32-bit x86 user space underneath it. This rare corner case is the only one that still needs the compat handlers.
By adding a simple redirect of .compat_ioctl to .unlocked_ioctl in the UML driver, we can remove all the COMPATIBLE_IOCTL() annotations without a change in functionality. For completeness, I'm adding the same thing to the dmasound file, knowing that it makes no difference.
The compat_ioctl list contains one comment about SNDCTL_DSP_MAPINBUF and SNDCTL_DSP_MAPOUTBUF, which actually would need a translation handler if implemented. However, the native implementation just returns -EINVAL, so we don't care.
Signed-off-by: Arnd Bergmann arnd@arndb.de
This looks like a really nice cleanup. Thanks!
Reviewed-by: Takashi Iwai tiwai@suse.de
Is this supposed to be taken via sound git tree, or would you apply over yours? I'm fine in either way.
thanks,
Takashi
On Mon, Apr 29, 2019 at 9:05 AM Takashi Iwai tiwai@suse.de wrote:
On Wed, 17 Apr 2019 10:05:33 +0200, Takashi Iwai wrote:
On Tue, 16 Apr 2019 22:28:05 +0200, Arnd Bergmann wrote:
The compat_ioctl list contains one comment about SNDCTL_DSP_MAPINBUF and SNDCTL_DSP_MAPOUTBUF, which actually would need a translation handler if implemented. However, the native implementation just returns -EINVAL, so we don't care.
Signed-off-by: Arnd Bergmann arnd@arndb.de
This looks like a really nice cleanup. Thanks!
Reviewed-by: Takashi Iwai tiwai@suse.de
Is this supposed to be taken via sound git tree, or would you apply over yours? I'm fine in either way.
I was hoping that Al could pick up the entire series to avoid the merge conflicts, but then we had some more discussion about the earlier patches in the series and he did another version of those.
Al, what is your current plan for the compat-ioctl removal series? Are you working on a combined series, or should I resend a subset of my patches to you?
Arnd
On 2019-04-16 4:19 p.m., Arnd Bergmann wrote:
Hi Al,
It took me way longer than I had hoped to revisit this series, see https://lore.kernel.org/lkml/20180912150142.157913-1-arnd@arndb.de/ for the previously posted version.
I've come to the point where all conversion handlers and most COMPATIBLE_IOCTL() entries are gone from this file, but for now, this series only has the parts that have either been reviewed previously, or that are simple enough to include.
The main missing piece is the SG_IO/SG_GET_REQUEST_TABLE conversion. I'll post the patches I made for that later, as they need more testing and review from the scsi maintainers.
Perhaps you could look at the document in this url: http://sg.danny.cz/sg/sg_v40.html
It is work-in-progress to modernize the SCSI generic driver. It extends ioctl(sg_fd, SG_IO, &pt_obj) to additionally accept the sg v4 interface as defined in include/uapi/linux/bsg.h . Currently only the bsg driver uses the sg v4 interface. Since struct sg_io_v4 is all explicitly sized integers, I'm guessing it is immune "compat" problems. [I can see no reference to bsg nor struct sg_io_v4 in the current fs/compat_ioctl.c file.]
Other additions described in the that document are these new ioctls: - SG_IOSUBMIT ultimately to replace write(sg_fd, ...) - SG_IORECEIVE to replace read(sg_fd, ...) - SG_IOABORT abort SCSI cmd in progress; new functionality - SG_SET_GET_EXTENDED has associated struct sg_extended_info
The first three take a pointer to a struct sg_io_hdr (v3 interface) or a struct sg_io_v4 object. Both objects start with a 32 bit integer: 'S' identifies the v3 interface while 'Q' identifies the v4 interface.
The SG_SET_GET_EXTENDED ioctl takes a pointer to a struct sg_extended_info object which contains explicitly sized integers so it may also be immune from "compat" problems. The ioctls section (13) of that document referenced above has a table showing how many "sets and gets" are hiding in the SG_SET_GET_EXTENDED ioctl.
BTW No change is proposed for this case: ioctl(normal_block_device, SG_IO, &sg_v3_obj) which is handled by block/scsi_ioctl.c
This would be a good time for me to address any "compat" concerns in the proposed sg driver update.
Doug Gilbert
I hope you can still take these for the coming merge window, unless new problems come up.
Arnd
Arnd Bergmann (26): compat_ioctl: pppoe: fix PPPOEIOCSFWD handling compat_ioctl: move simple ppp command handling into driver compat_ioctl: avoid unused function warning for do_ioctl compat_ioctl: move PPPIOCSCOMPRESS32 to ppp-generic.c compat_ioctl: move PPPIOCSPASS32/PPPIOCSACTIVE32 to ppp_generic.c compat_ioctl: handle PPPIOCGIDLE for 64-bit time_t compat_ioctl: move rtc handling into rtc-dev.c compat_ioctl: add compat_ptr_ioctl() compat_ioctl: move drivers to compat_ptr_ioctl compat_ioctl: use correct compat_ptr() translation in drivers ceph: fix compat_ioctl for ceph_dir_operations compat_ioctl: move more drivers to compat_ptr_ioctl compat_ioctl: move tape handling into drivers compat_ioctl: move ATYFB_CLK handling to atyfb driver compat_ioctl: move isdn/capi ioctl translation into driver compat_ioctl: move rfcomm handlers into driver compat_ioctl: move hci_sock handlers into driver compat_ioctl: remove HCIUART handling compat_ioctl: remove HIDIO translation compat_ioctl: remove translation for sound ioctls compat_ioctl: remove IGNORE_IOCTL() compat_ioctl: remove /dev/random commands compat_ioctl: remove joystick ioctl translation compat_ioctl: remove PCI ioctl translation compat_ioctl: remove /dev/raw ioctl translation compat_ioctl: remove last RAID handling code
Documentation/networking/ppp_generic.txt | 2 + arch/um/drivers/hostaudio_kern.c | 1 + drivers/android/binder.c | 2 +- drivers/char/ppdev.c | 12 +- drivers/char/random.c | 1 + drivers/char/tpm/tpm_vtpm_proxy.c | 12 +- 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/firewire/core-cdev.c | 12 +- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/hid/hidraw.c | 4 +- drivers/hid/usbhid/hiddev.c | 11 +- drivers/hwtracing/stm/core.c | 12 +- drivers/ide/ide-tape.c | 31 +- drivers/iio/industrialio-core.c | 2 +- drivers/infiniband/core/uverbs_main.c | 4 +- drivers/isdn/capi/capi.c | 31 + drivers/isdn/i4l/isdn_ppp.c | 14 +- drivers/media/rc/lirc_dev.c | 4 +- drivers/mfd/cros_ec_dev.c | 4 +- drivers/misc/cxl/flash.c | 8 +- drivers/misc/genwqe/card_dev.c | 23 +- drivers/misc/mei/main.c | 22 +- drivers/misc/vmw_vmci/vmci_host.c | 2 +- drivers/mtd/ubi/cdev.c | 36 +- drivers/net/ppp/ppp_generic.c | 99 +++- drivers/net/ppp/pppoe.c | 7 + drivers/net/ppp/pptp.c | 3 + drivers/net/tap.c | 12 +- 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/rtc/dev.c | 13 +- drivers/rtc/rtc-vr41xx.c | 10 + drivers/s390/char/tape_char.c | 41 +- 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/megaraid/megaraid_mm.c | 28 +- drivers/scsi/osst.c | 34 +- drivers/scsi/pmcraid.c | 4 +- drivers/scsi/st.c | 35 +- drivers/staging/android/ion/ion.c | 4 +- drivers/staging/pi433/pi433_if.c | 12 +- 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/usb/core/devio.c | 16 +- drivers/usb/gadget/function/f_fs.c | 12 +- 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 +- drivers/video/fbdev/aty/atyfb_base.c | 12 +- drivers/virt/fsl_hypervisor.c | 2 +- fs/btrfs/super.c | 2 +- fs/ceph/dir.c | 1 + fs/ceph/file.c | 2 +- fs/compat_ioctl.c | 602 +------------------- fs/fat/file.c | 13 +- fs/fuse/dev.c | 2 +- fs/notify/fanotify/fanotify_user.c | 2 +- fs/userfaultfd.c | 2 +- include/linux/fs.h | 7 + include/linux/if_pppox.h | 2 + include/linux/mtio.h | 58 ++ include/uapi/linux/ppp-ioctl.h | 2 + include/uapi/linux/ppp_defs.h | 14 + net/bluetooth/hci_sock.c | 21 +- net/bluetooth/rfcomm/sock.c | 14 +- net/l2tp/l2tp_ppp.c | 3 + net/rfkill/core.c | 2 +- sound/core/oss/pcm_oss.c | 4 + sound/oss/dmasound/dmasound_core.c | 2 + 82 files changed, 452 insertions(+), 1034 deletions(-) create mode 100644 include/linux/mtio.h
On Wed, Apr 17, 2019 at 12:33 AM Douglas Gilbert dgilbert@interlog.com wrote:
On 2019-04-16 4:19 p.m., Arnd Bergmann wrote:
Hi Al,
It took me way longer than I had hoped to revisit this series, see https://lore.kernel.org/lkml/20180912150142.157913-1-arnd@arndb.de/ for the previously posted version.
I've come to the point where all conversion handlers and most COMPATIBLE_IOCTL() entries are gone from this file, but for now, this series only has the parts that have either been reviewed previously, or that are simple enough to include.
The main missing piece is the SG_IO/SG_GET_REQUEST_TABLE conversion. I'll post the patches I made for that later, as they need more testing and review from the scsi maintainers.
Perhaps you could look at the document in this url: http://sg.danny.cz/sg/sg_v40.html
It is work-in-progress to modernize the SCSI generic driver. It extends ioctl(sg_fd, SG_IO, &pt_obj) to additionally accept the sg v4 interface as defined in include/uapi/linux/bsg.h . Currently only the bsg driver uses the sg v4 interface. Since struct sg_io_v4 is all explicitly sized integers, I'm guessing it is immune "compat" problems. [I can see no reference to bsg nor struct sg_io_v4 in the current fs/compat_ioctl.c file.]
Ok, I've taken a brief look at your series now. Unfortunately it clashes quite hard with my series, but it's probably for the better to have your stuff get merged first.
A few (unsorted) comments from going through your patches:
- the added ioctls are all compatible when using the v4 structures and mostly don't need handlers for compat mode, but they need to be called from .compat_ioctl to actually be usable in compat mode. With my patches you get that. - One exception for the v4 layout is the use of iovec pointers, as 'struct iovec' is incompatible. We should probably merge the generic compat_import_iovec() into import_iovec() with a 'in_compat_syscall()' check, which would be helpful in general. bsg.c does not iovec, so it is not affected by this at the moment, maybe it would be better to stay compatible with that and also not support them in sg.c? - Is there a need for the new sg_ioctl_iosubmit/sg_ioctl_ioreceive to support the v3 structures? Those are /not/ compatible, so you need extra code to handle the v3-compat layout as well. Supporting only v4 would simplify this. - the lack of changeset descriptions is a bit irritating and makes it much harder to understand what you are doing. - try to keep patches that move code around separate from those that change it in any other way, for better reviewing. - in "sg: preparation for request sharing", you seem to inadvertently change the size of "struct sg_extended_info", making it 4 bytes longer by adding two members. - You should never use IS_ERR_OR_NULL() in normal code, that is just a sign of a bad API. Make each function have consistent error behavior. - The "#if 0 /* temporary to shorten big patch */" trick breaks bisection, that is probably worse than the larger patch. - The split access_ok()/__copy_from_user() has fallen out of favor because it has caused too many bugs in the past, just use the combined copy_from_user() instead. - ktime_to_ns(ktime_get_with_offset(TK_OFFS_BOOT)) followed by a 64-bit division won't work on 32-bit machines, use ktime_get_boottime_ts64() instead.
Other additions described in the that document are these new ioctls:
- SG_IOSUBMIT ultimately to replace write(sg_fd, ...)
- SG_IORECEIVE to replace read(sg_fd, ...)
- SG_IOABORT abort SCSI cmd in progress; new functionality
- SG_SET_GET_EXTENDED has associated struct sg_extended_info
The first three take a pointer to a struct sg_io_hdr (v3 interface) or a struct sg_io_v4 object. Both objects start with a 32 bit integer: 'S' identifies the v3 interface while 'Q' identifies the v4 interface.
I think the magic character was a mistake in the original design, just like versioned interfaces in general. If you are extending an interface in an incompatible way, the normal way would be to have separate command codes, like SG_IORECEIVE_V3 and SG_IORECEIVE_V4, if you absolutely have to maintain compatiblity with the old interface (which I think you don't in case of SG_IORECEIVE).
For SG_IO, I can see why you want to support both the v3 and v4 structures plus the compat-v3 version, but I'd try to keep them as separate as possible, and do something like
static int sg_ctl_sg_io(struct file *filp, struct sg_device *sdp, struct sg_fd *sfp, void __user *p) { int ret;
ret = sg_io_v4(filp, sdp, sfp, (struct sg_io_v4 __user *)p);
if (ret != -ENOIOCTLCMD || !S_ENABLED(CONFIG_SG_IO_V3)) return ret;
if (in_compat_syscall()) ret = sg_io_compat_(filp, sdp, sfp, (struct compat_sg_io_hdr __user *)p); else ret = sg_io_v3(filp, sdp, sfp, (struct sg_io_hdr __user *)p); }
In my patch series, I combined the latter two cases and used a shared get_sg_io_hdr()/put_sg_io_hdr() helper as well as a wrapper for the iovec issue.
The SG_SET_GET_EXTENDED ioctl takes a pointer to a struct sg_extended_info object which contains explicitly sized integers so it may also be immune from "compat" problems. The ioctls section (13) of that document referenced above has a table showing how many "sets and gets" are hiding in the SG_SET_GET_EXTENDED ioctl.
Agreed, SG_SET_GET_EXTENDED looks fine to me from a compat perspective.
I've uploaded my patches to git://git.kernel.org:/pub/scm/linux/kernel/git/arnd/playground.git compat-ioctl-v3 This contains both the series I posted here, and my scsi ioctl rework.
Maybe you can take the bits you need from that to handle the v3-compat structures and integrate it into your series?
Arnd
On Tue, Apr 16, 2019 at 11:23 PM Arnd Bergmann arnd@arndb.de wrote:
Hi Al,
It took me way longer than I had hoped to revisit this series, see https://lore.kernel.org/lkml/20180912150142.157913-1-arnd@arndb.de/ for the previously posted version.
I've come to the point where all conversion handlers and most COMPATIBLE_IOCTL() entries are gone from this file, but for now, this series only has the parts that have either been reviewed previously, or that are simple enough to include.
The main missing piece is the SG_IO/SG_GET_REQUEST_TABLE conversion. I'll post the patches I made for that later, as they need more testing and review from the scsi maintainers.
I hope you can still take these for the coming merge window, unless new problems come up.
drivers/platform/x86/wmi.c | 2 +-
Acked-by: Andy Shevchenko andy.shevchenko@gmail.com