sx: push BKL down into the firmware ioctl handler

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>
This commit is contained in:
Alan Cox 2008-07-25 01:48:15 -07:00 committed by Linus Torvalds
parent f6759fdcfd
commit 11af7478ad

View 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;
}