cleanup compat ioctl handling
authorChristoph Hellwig <hch@lst.de>
Tue, 8 May 2007 07:29:21 +0000 (00:29 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 8 May 2007 18:15:09 +0000 (11:15 -0700)
Merge all compat ioctl handling into compat_ioctl.c instead of splitting it
over compat.c and compat_ioctl.c.  This also allows to get rid of ioctl32.h

Signed-off-by: Christoph Hellwig <hch@lst.de>
Looks-good-to: Andi Kleen <ak@suse.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/compat.c
fs/compat_ioctl.c
fs/internal.h
include/linux/ioctl32.h [deleted file]
include/net/sock.h

index a32e2ae..9f6248d 100644 (file)
 #include <linux/namei.h>
 #include <linux/file.h>
 #include <linux/vfs.h>
-#include <linux/ioctl32.h>
 #include <linux/ioctl.h>
 #include <linux/init.h>
-#include <linux/sockios.h>     /* for SIOCDEVPRIVATE */
 #include <linux/smb.h>
 #include <linux/smb_mount.h>
 #include <linux/ncp_mount.h>
 #include <linux/personality.h>
 #include <linux/rwsem.h>
 #include <linux/tsacct_kern.h>
+#include <linux/security.h>
 #include <linux/highmem.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
 #include <linux/eventpoll.h>
 
-#include <net/sock.h>          /* siocdevprivate_ioctl */
-
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/ioctls.h>
@@ -313,163 +310,6 @@ out:
        return error;
 }
 
-/* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */
-
-#define IOCTL_HASHSIZE 256
-static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
-
-static inline unsigned long ioctl32_hash(unsigned long cmd)
-{
-       return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
-}
-
-static void ioctl32_insert_translation(struct ioctl_trans *trans)
-{
-       unsigned long hash;
-       struct ioctl_trans *t;
-
-       hash = ioctl32_hash (trans->cmd);
-       if (!ioctl32_hash_table[hash])
-               ioctl32_hash_table[hash] = trans;
-       else {
-               t = ioctl32_hash_table[hash];
-               while (t->next)
-                       t = t->next;
-               trans->next = NULL;
-               t->next = trans;
-       }
-}
-
-static int __init init_sys32_ioctl(void)
-{
-       int i;
-
-       for (i = 0; i < ioctl_table_size; i++) {
-               if (ioctl_start[i].next != 0) { 
-                       printk("ioctl translation %d bad\n",i); 
-                       return -1;
-               }
-
-               ioctl32_insert_translation(&ioctl_start[i]);
-       }
-       return 0;
-}
-
-__initcall(init_sys32_ioctl);
-
-static void compat_ioctl_error(struct file *filp, unsigned int fd,
-               unsigned int cmd, unsigned long arg)
-{
-       char buf[10];
-       char *fn = "?";
-       char *path;
-
-       /* find the name of the device. */
-       path = (char *)__get_free_page(GFP_KERNEL);
-       if (path) {
-               fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
-               if (IS_ERR(fn))
-                       fn = "?";
-       }
-
-       sprintf(buf,"'%c'", (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK);
-       if (!isprint(buf[1]))
-               sprintf(buf, "%02x", buf[1]);
-       compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
-                       "cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n",
-                       current->comm, current->pid,
-                       (int)fd, (unsigned int)cmd, buf,
-                       (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK,
-                       (unsigned int)arg, fn);
-
-       if (path)
-               free_page((unsigned long)path);
-}
-
-asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
-                               unsigned long arg)
-{
-       struct file *filp;
-       int error = -EBADF;
-       struct ioctl_trans *t;
-       int fput_needed;
-
-       filp = fget_light(fd, &fput_needed);
-       if (!filp)
-               goto out;
-
-       /* RED-PEN how should LSM module know it's handling 32bit? */
-       error = security_file_ioctl(filp, cmd, arg);
-       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) {
-       case FIOCLEX:
-       case FIONCLEX:
-       case FIONBIO:
-       case FIOASYNC:
-       case FIOQSIZE:
-               break;
-
-       case FIBMAP:
-       case FIGETBSZ:
-       case FIONREAD:
-               if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
-                       break;
-               /*FALL THROUGH*/
-
-       default:
-               if (filp->f_op && filp->f_op->compat_ioctl) {
-                       error = filp->f_op->compat_ioctl(filp, cmd, arg);
-                       if (error != -ENOIOCTLCMD)
-                               goto out_fput;
-               }
-
-               if (!filp->f_op ||
-                   (!filp->f_op->ioctl && !filp->f_op->unlocked_ioctl))
-                       goto do_ioctl;
-               break;
-       }
-
-       for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) {
-               if (t->cmd == cmd)
-                       goto found_handler;
-       }
-
-       if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
-           cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
-               error = siocdevprivate_ioctl(fd, cmd, arg);
-       } else {
-               static int count;
-
-               if (++count <= 50)
-                       compat_ioctl_error(filp, fd, cmd, arg);
-               error = -EINVAL;
-       }
-
-       goto out_fput;
-
- found_handler:
-       if (t->handler) {
-               lock_kernel();
-               error = t->handler(fd, cmd, arg, filp);
-               unlock_kernel();
-               goto out_fput;
-       }
-
- do_ioctl:
-       error = vfs_ioctl(filp, fd, cmd, arg);
- out_fput:
-       fput_light(filp, fput_needed);
- out:
-       return error;
-}
-
 static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
 {
        if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
index a0c3d20..6972d24 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/serial.h>
 #include <linux/if_tun.h>
 #include <linux/ctype.h>
-#include <linux/ioctl32.h>
 #include <linux/syscalls.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
@@ -65,7 +64,6 @@
 #include <linux/atalk.h>
 #include <linux/blktrace_api.h>
 
-#include <net/sock.h>          /* siocdevprivate_ioctl */
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci.h>
 #include <net/bluetooth/rfcomm.h>
@@ -474,7 +472,7 @@ static int bond_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
        };
 }
 
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
        struct ifreq __user *u_ifreq64;
        struct ifreq32 __user *u_ifreq32 = compat_ptr(arg);
@@ -2384,6 +2382,16 @@ lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
        return sys_ioctl(fd, cmd, (unsigned long)tn);
 }
 
+
+typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
+                                       unsigned long, struct file *);
+
+struct ioctl_trans {
+       unsigned long cmd;
+       ioctl_trans_handler_t handler;
+       struct ioctl_trans *next;
+};
+
 #define HANDLE_IOCTL(cmd,handler) \
        { (cmd), (ioctl_trans_handler_t)(handler) },
 
@@ -2404,7 +2412,7 @@ lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
    Most other reasons are not valid. */
 #define IGNORE_IOCTL(cmd) COMPATIBLE_IOCTL(cmd)
 
-struct ioctl_trans ioctl_start[] = {
+static struct ioctl_trans ioctl_start[] = {
 /* compatible ioctls first */
 COMPATIBLE_IOCTL(0x4B50)   /* KDGHWCLK - not in the kernel, but don't complain */
 COMPATIBLE_IOCTL(0x4B51)   /* KDSHWCLK - not in the kernel, but don't complain */
@@ -3464,4 +3472,156 @@ IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32)
 IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
 };
 
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
+#define IOCTL_HASHSIZE 256
+static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+
+static inline unsigned long ioctl32_hash(unsigned long cmd)
+{
+       return (((cmd >> 6) ^ (cmd >> 4) ^ cmd)) % IOCTL_HASHSIZE;
+}
+
+static void compat_ioctl_error(struct file *filp, unsigned int fd,
+               unsigned int cmd, unsigned long arg)
+{
+       char buf[10];
+       char *fn = "?";
+       char *path;
+
+       /* find the name of the device. */
+       path = (char *)__get_free_page(GFP_KERNEL);
+       if (path) {
+               fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE);
+               if (IS_ERR(fn))
+                       fn = "?";
+       }
+
+        sprintf(buf,"'%c'", (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK);
+       if (!isprint(buf[1]))
+               sprintf(buf, "%02x", buf[1]);
+       compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
+                       "cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n",
+                       current->comm, current->pid,
+                       (int)fd, (unsigned int)cmd, buf,
+                       (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK,
+                       (unsigned int)arg, fn);
+
+       if (path)
+               free_page((unsigned long)path);
+}
+
+asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct file *filp;
+       int error = -EBADF;
+       struct ioctl_trans *t;
+       int fput_needed;
+
+       filp = fget_light(fd, &fput_needed);
+       if (!filp)
+               goto out;
+
+       /* RED-PEN how should LSM module know it's handling 32bit? */
+       error = security_file_ioctl(filp, cmd, arg);
+       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) {
+       case FIOCLEX:
+       case FIONCLEX:
+       case FIONBIO:
+       case FIOASYNC:
+       case FIOQSIZE:
+               break;
+
+       case FIBMAP:
+       case FIGETBSZ:
+       case FIONREAD:
+               if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+                       break;
+               /*FALL THROUGH*/
+
+       default:
+               if (filp->f_op && filp->f_op->compat_ioctl) {
+                       error = filp->f_op->compat_ioctl(filp, cmd, arg);
+                       if (error != -ENOIOCTLCMD)
+                               goto out_fput;
+               }
+
+               if (!filp->f_op ||
+                   (!filp->f_op->ioctl && !filp->f_op->unlocked_ioctl))
+                       goto do_ioctl;
+               break;
+       }
+
+       for (t = ioctl32_hash_table[ioctl32_hash(cmd)]; t; t = t->next) {
+               if (t->cmd == cmd)
+                       goto found_handler;
+       }
+
+       if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
+           cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
+               error = siocdevprivate_ioctl(fd, cmd, arg);
+       } else {
+               static int count;
+
+               if (++count <= 50)
+                       compat_ioctl_error(filp, fd, cmd, arg);
+               error = -EINVAL;
+       }
+
+       goto out_fput;
+
+ found_handler:
+       if (t->handler) {
+               lock_kernel();
+               error = t->handler(fd, cmd, arg, filp);
+               unlock_kernel();
+               goto out_fput;
+       }
+
+ do_ioctl:
+       error = vfs_ioctl(filp, fd, cmd, arg);
+ out_fput:
+       fput_light(filp, fput_needed);
+ out:
+       return error;
+}
+
+static void ioctl32_insert_translation(struct ioctl_trans *trans)
+{
+       unsigned long hash;
+       struct ioctl_trans *t;
+
+       hash = ioctl32_hash (trans->cmd);
+       if (!ioctl32_hash_table[hash])
+               ioctl32_hash_table[hash] = trans;
+       else {
+               t = ioctl32_hash_table[hash];
+               while (t->next)
+                       t = t->next;
+               trans->next = NULL;
+               t->next = trans;
+       }
+}
+
+static int __init init_sys32_ioctl(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ioctl_start); i++) {
+               if (ioctl_start[i].next != 0) {
+                       printk("ioctl translation %d bad\n",i);
+                       return -1;
+               }
+
+               ioctl32_insert_translation(&ioctl_start[i]);
+       }
+       return 0;
+}
+__initcall(init_sys32_ioctl);
index ea00126..392e8cc 100644 (file)
@@ -9,8 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/ioctl32.h>
-
 struct super_block;
 
 /*
@@ -42,14 +40,6 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
 extern void __init chrdev_init(void);
 
 /*
- * compat_ioctl.c
- */
-#ifdef CONFIG_COMPAT
-extern struct ioctl_trans ioctl_start[];
-extern int ioctl_table_size;
-#endif
-
-/*
  * namespace.c
  */
 extern int copy_mount_options(const void __user *, unsigned long *);
diff --git a/include/linux/ioctl32.h b/include/linux/ioctl32.h
deleted file mode 100644 (file)
index 948809d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef IOCTL32_H
-#define IOCTL32_H 1
-
-#include <linux/compiler.h>    /* for __deprecated */
-
-struct file;
-
-typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
-                                       unsigned long, struct file *);
-
-struct ioctl_trans {
-       unsigned long cmd;
-       ioctl_trans_handler_t handler;
-       struct ioctl_trans *next;
-};
-
-#endif
index 25c37e3..689b886 100644 (file)
@@ -1361,15 +1361,6 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
 extern __u32 sysctl_wmem_max;
 extern __u32 sysctl_rmem_max;
 
-#ifdef CONFIG_NET
-int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-#else
-static inline int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       return -ENODEV;
-}
-#endif
-
 extern void sk_init(void);
 
 #ifdef CONFIG_SYSCTL