summaryrefslogtreecommitdiffstats
path: root/fs/ioctl.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2019-06-07 10:06:42 +0200
committerArnd Bergmann <arnd@arndb.de>2020-01-03 09:42:52 +0100
commit2af563d071d63ac820354e4b275478a481845071 (patch)
tree83902dda83eafcb0be97cf93238fcc1697691d5d /fs/ioctl.c
parentcompat_ioctl: scsi: move ioctl handling into drivers (diff)
downloadlinux-2af563d071d63ac820354e4b275478a481845071.tar.xz
linux-2af563d071d63ac820354e4b275478a481845071.zip
compat_ioctl: move sys_compat_ioctl() to ioctl.c
The rest of the fs/compat_ioctl.c file is no longer useful now, so move the actual syscall as planned. Reviewed-by: Ben Hutchings <ben.hutchings@codethink.co.uk> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r--fs/ioctl.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 2f5e4e5b97e1..8f22f7817edb 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -788,4 +788,94 @@ long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
}
EXPORT_SYMBOL(compat_ptr_ioctl);
+
+COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
+ compat_ulong_t, arg32)
+{
+ unsigned long arg = arg32;
+ struct fd f = fdget(fd);
+ int error = -EBADF;
+ if (!f.file)
+ goto out;
+
+ /* RED-PEN how should LSM module know it's handling 32bit? */
+ error = security_file_ioctl(f.file, cmd, arg);
+ if (error)
+ goto out_fput;
+
+ switch (cmd) {
+ /* these are never seen by ->ioctl(), no argument or int argument */
+ case FIOCLEX:
+ case FIONCLEX:
+ case FIFREEZE:
+ case FITHAW:
+ case FICLONE:
+ goto do_ioctl;
+ /* these are never seen by ->ioctl(), pointer argument */
+ case FIONBIO:
+ case FIOASYNC:
+ case FIOQSIZE:
+ case FS_IOC_FIEMAP:
+ case FIGETBSZ:
+ case FICLONERANGE:
+ case FIDEDUPERANGE:
+ goto found_handler;
+ /*
+ * The next group is the stuff handled inside file_ioctl().
+ * For regular files these never reach ->ioctl(); for
+ * devices, sockets, etc. they do and one (FIONREAD) is
+ * even accepted in some cases. In all those cases
+ * argument has the same type, so we can handle these
+ * here, shunting them towards do_vfs_ioctl().
+ * ->compat_ioctl() will never see any of those.
+ */
+ /* pointer argument, never actually handled by ->ioctl() */
+ case FIBMAP:
+ goto found_handler;
+ /* handled by some ->ioctl(); always a pointer to int */
+ case FIONREAD:
+ goto found_handler;
+ /* these get messy on amd64 due to alignment differences */
+#if defined(CONFIG_X86_64)
+ case FS_IOC_RESVSP_32:
+ case FS_IOC_RESVSP64_32:
+ error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
+ goto out_fput;
+ case FS_IOC_UNRESVSP_32:
+ case FS_IOC_UNRESVSP64_32:
+ error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
+ compat_ptr(arg));
+ goto out_fput;
+ case FS_IOC_ZERO_RANGE_32:
+ error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
+ compat_ptr(arg));
+ goto out_fput;
+#else
+ case FS_IOC_RESVSP:
+ case FS_IOC_RESVSP64:
+ case FS_IOC_UNRESVSP:
+ case FS_IOC_UNRESVSP64:
+ case FS_IOC_ZERO_RANGE:
+ goto found_handler;
+#endif
+
+ default:
+ if (f.file->f_op->compat_ioctl) {
+ error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
+ if (error != -ENOIOCTLCMD)
+ goto out_fput;
+ }
+ error = -ENOTTY;
+ goto out_fput;
+ }
+
+ found_handler:
+ arg = (unsigned long)compat_ptr(arg);
+ do_ioctl:
+ error = do_vfs_ioctl(f.file, fd, cmd, arg);
+ out_fput:
+ fdput(f);
+ out:
+ return error;
+}
#endif