sx: Push BKL down into the firmware ioctl handler
PATCH 1/1 sx: Push BKL down into the firmware ioctl handler
Also fix the capability checking for firmware load.
Signed-off-by Alan Cox <[email protected]>
drivers/char/sx.c +43 -30
@@ -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; }