diff mbox series

[v6,06/43] compat_sys_ioctl(): make parallel to do_vfs_ioctl()

Message ID 20191009191044.308087-6-arnd@arndb.de
State New
Headers show
Series [v6,01/43] fix compat handling of FICLONERANGE, FIDEDUPERANGE and FS_IOC_FIEMAP | expand

Commit Message

Arnd Bergmann Oct. 9, 2019, 7:10 p.m. UTC
From: Al Viro <viro@zeniv.linux.org.uk>


Handle ioctls that might be handled without reaching ->ioctl() in
native case on the top level there.  The counterpart of vfs_ioctl()
(i.e. calling ->unlock_ioctl(), etc.) left as-is; eventually
that would turn simply into the call of ->compat_ioctl(), but
that'll take more work.  Once that is done, we can move the
remains of compat_sys_ioctl() into fs/ioctl.c and finally bury
fs/compat_ioctl.c.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

---
 fs/compat_ioctl.c | 63 +++++++++++++++++++++--------------------------
 1 file changed, 28 insertions(+), 35 deletions(-)

-- 
2.20.0
diff mbox series

Patch

diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index ce995d4fa1f4..ecbd5254b547 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -487,19 +487,7 @@  static unsigned int ioctl_pointer[] = {
 /* compatible ioctls first */
 /* Little t */
 COMPATIBLE_IOCTL(TIOCOUTQ)
-/* Little f */
-COMPATIBLE_IOCTL(FIOCLEX)
-COMPATIBLE_IOCTL(FIONCLEX)
-COMPATIBLE_IOCTL(FIOASYNC)
-COMPATIBLE_IOCTL(FIONBIO)
-COMPATIBLE_IOCTL(FIONREAD)  /* This is also TIOCINQ */
-COMPATIBLE_IOCTL(FS_IOC_FIEMAP)
-/* 0x00 */
-COMPATIBLE_IOCTL(FIBMAP)
-COMPATIBLE_IOCTL(FIGETBSZ)
 /* 'X' - originally XFS but some now in the VFS */
-COMPATIBLE_IOCTL(FIFREEZE)
-COMPATIBLE_IOCTL(FITHAW)
 COMPATIBLE_IOCTL(FITRIM)
 #ifdef CONFIG_BLOCK
 /* Big S */
@@ -971,19 +959,39 @@  COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
 	if (error)
 		goto out_fput;
 
-	/*
-	 * To allow the compat_ioctl handlers to be self contained
-	 * we need to check the common ioctls here first.
-	 * Just handle them with the standard handlers below.
-	 */
 	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:
-		break;
-
+	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 two get messy on amd64 due to alignment differences */
 #if defined(CONFIG_X86_64)
 	case FS_IOC_RESVSP_32:
 	case FS_IOC_RESVSP64_32:
@@ -992,23 +1000,8 @@  COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
 #else
 	case FS_IOC_RESVSP:
 	case FS_IOC_RESVSP64:
-		error = ioctl_preallocate(f.file, compat_ptr(arg));
-		goto out_fput;
-#endif
-
-	case FICLONE:
-		goto do_ioctl;
-	case FICLONERANGE:
-	case FIDEDUPERANGE:
-	case FS_IOC_FIEMAP:
-	case FIGETBSZ:
 		goto found_handler;
-
-	case FIBMAP:
-	case FIONREAD:
-		if (S_ISREG(file_inode(f.file)->i_mode))
-			break;
-		/*FALL THROUGH*/
+#endif
 
 	default:
 		if (f.file->f_op->compat_ioctl) {