sx: push BKL down into the firmware ioctl handler
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 25 Jul 2008 08:48:15 +0000 (01:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 25 Jul 2008 17:53:43 +0000 (10:53 -0700)
Also fix the capability checking for firmware load.

Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/sx.c

index 2162439bbe487544c589c6f0c054e6d849257a94..c385206f9db540caa925d615be1c1d4d566482f4 100644 (file)
@@ -286,8 +286,8 @@ static void sx_close(void *ptr);
 static int sx_chars_in_buffer(void *ptr);
 static int sx_init_board(struct sx_board *board);
 static int sx_init_portstructs(int nboards, int nports);
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg);
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+                                               unsigned long arg);
 static int sx_init_drivers(void);
 
 static struct tty_driver *sx_driver;
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
 
 static const struct file_operations sx_fw_fops = {
        .owner = THIS_MODULE,
-       .ioctl = sx_fw_ioctl,
+       .unlocked_ioctl = sx_fw_ioctl,
 };
 
 static struct miscdevice sx_fw_device = {
@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max)
 }
 #endif
 
-static int sx_fw_ioctl(struct inode *inode, struct file *filp,
-               unsigned int cmd, unsigned long arg)
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+                                                       unsigned long arg)
 {
-       int rc = 0;
+       long rc = 0;
        int __user *descr = (int __user *)arg;
        int i;
        static struct sx_board *board = NULL;
@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
 
        func_enter();
 
-#if 0
-       /* Removed superuser check: Sysops can use the permissions on the device
-          file to restrict access. Recommendation: Root only. (root.root 600) */
-       if (!capable(CAP_SYS_ADMIN)) {
+       if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
-       }
-#endif
+
+       lock_kernel();
 
        sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
 
@@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                for (i = 0; i < SX_NBOARDS; i++)
                        sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
                sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
+               unlock_kernel();
                return -EIO;
        }
 
        switch (cmd) {
        case SXIO_SET_BOARD:
                sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
+               rc = -EIO;
                if (arg >= SX_NBOARDS)
-                       return -EIO;
+                       break;
                sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
                if (!(boards[arg].flags & SX_BOARD_PRESENT))
-                       return -EIO;
+                       break;
                sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
                board = &boards[arg];
+               rc = 0;
+               /* FIXME: And this does ... nothing?? */
                break;
        case SXIO_GET_TYPE:
                rc = -ENOENT;   /* If we manage to miss one, return error. */
@@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                        rc = SX_TYPE_SI;
                if (IS_EISA_BOARD(board))
                        rc = SX_TYPE_SI;
-               sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc);
+               sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
                break;
        case SXIO_DO_RAMTEST:
                if (sx_initialized)     /* Already initialized: better not ramtest the board.  */
@@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                        rc = do_memtest(board, 0, 0x7ff8);
                        /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
                }
-               sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n",
-                          rc);
+               sx_dprintk(SX_DEBUG_FIRMWARE,
+                               "returning memtest result= %ld\n", rc);
                break;
        case SXIO_DOWNLOAD:
-               if (sx_initialized)     /* Already initialized */
-                       return -EEXIST;
-               if (!sx_reset(board))
-                       return -EIO;
+               if (sx_initialized) {/* Already initialized */
+                       rc = -EEXIST;
+                       break;
+               }
+               if (!sx_reset(board)) {
+                       rc = -EIO;
+                       break;
+               }
                sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
 
                tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
-               if (!tmp)
-                       return -ENOMEM;
+               if (!tmp) {
+                       rc = -ENOMEM;
+                       break;
+               }
+               /* FIXME: check returns */
                get_user(nbytes, descr++);
                get_user(offset, descr++);
                get_user(data, descr++);
@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                                                (i + SX_CHUNK_SIZE > nbytes) ?
                                                nbytes - i : SX_CHUNK_SIZE)) {
                                        kfree(tmp);
-                                       return -EFAULT;
+                                       rc = -EFAULT;
+                                       break;
                                }
                                memcpy_toio(board->base2 + offset + i, tmp,
                                                (i + SX_CHUNK_SIZE > nbytes) ?
@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                rc = sx_nports;
                break;
        case SXIO_INIT:
-               if (sx_initialized)     /* Already initialized */
-                       return -EEXIST;
+               if (sx_initialized) {   /* Already initialized */
+                       rc = -EEXIST;
+                       break;
+               }
                /* This is not allowed until all boards are initialized... */
                for (i = 0; i < SX_NBOARDS; i++) {
                        if ((boards[i].flags & SX_BOARD_PRESENT) &&
-                               !(boards[i].flags & SX_BOARD_INITIALIZED))
-                               return -EIO;
+                               !(boards[i].flags & SX_BOARD_INITIALIZED)) {
+                               rc = -EIO;
+                               break;
+                       }
                }
                for (i = 0; i < SX_NBOARDS; i++)
                        if (!(boards[i].flags & SX_BOARD_PRESENT))
@@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
                rc = sx_nports;
                break;
        default:
-               printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n",
-                               cmd);
+               rc = -ENOTTY;
                break;
        }
+       unlock_kernel();
        func_exit();
        return rc;
 }