From 40f53a7cdc88503b648dcfef5ed2dcb86038dbba Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Fri, 22 Sep 2017 08:12:08 +0000 Subject: [PATCH] Add support for 32-bit compatibility IOCTLs in the LinuxKPI. Bump the FreeBSD version to force recompilation of external kernel modules due to structure change. PR: 222504 Submitted by: Greg V MFC after: 1 week Sponsored by: Mellanox Technologies --- sys/compat/linuxkpi/common/include/linux/fs.h | 2 +- sys/compat/linuxkpi/common/src/linux_compat.c | 15 ++++++++++++++- sys/sys/param.h | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h index 12f3a46f3b98..04fc78df4913 100644 --- a/sys/compat/linuxkpi/common/include/linux/fs.h +++ b/sys/compat/linuxkpi/common/include/linux/fs.h @@ -137,6 +137,7 @@ struct file_operations { ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long); + long (*compat_ioctl)(struct file *, unsigned int, unsigned long); int (*mmap)(struct file *, struct vm_area_struct *); int (*open)(struct inode *, struct file *); int (*release)(struct inode *, struct file *); @@ -157,7 +158,6 @@ struct file_operations { int (*readdir)(struct file *, void *, filldir_t); int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long); - long (*compat_ioctl)(struct file *, unsigned int, unsigned long); int (*flush)(struct file *, fl_owner_t id); int (*fsync)(struct file *, struct dentry *, int datasync); int (*aio_fsync)(struct kiocb *, int datasync); diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index ce2cf2e75a4a..ca57bfae1c09 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -906,7 +906,20 @@ linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, /* fetch user-space pointer */ data = *(void **)data; } - if (filp->f_op->unlocked_ioctl) +#if defined(__amd64__) + if (td->td_proc->p_elf_machine == EM_386) { + /* try the compat IOCTL handler first */ + if (filp->f_op->compat_ioctl != NULL) + error = -filp->f_op->compat_ioctl(filp, cmd, (u_long)data); + else + error = ENOTTY; + + /* fallback to the regular IOCTL handler, if any */ + if (error == ENOTTY && filp->f_op->unlocked_ioctl != NULL) + error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data); + } else +#endif + if (filp->f_op->unlocked_ioctl != NULL) error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data); else error = ENOTTY; diff --git a/sys/sys/param.h b/sys/sys/param.h index fac2da7727cb..ba366cd83216 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1200045 /* Master, propagated to newvers */ +#define __FreeBSD_version 1200046 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,