Commit 11af7478 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

sx: push BKL down into the firmware ioctl handler

Also fix the capability checking for firmware load.
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f6759fdc
...@@ -286,8 +286,8 @@ static void sx_close(void *ptr); ...@@ -286,8 +286,8 @@ static void sx_close(void *ptr);
static int sx_chars_in_buffer(void *ptr); static int sx_chars_in_buffer(void *ptr);
static int sx_init_board(struct sx_board *board); static int sx_init_board(struct sx_board *board);
static int sx_init_portstructs(int nboards, int nports); static int sx_init_portstructs(int nboards, int nports);
static int sx_fw_ioctl(struct inode *inode, struct file *filp, static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
unsigned int cmd, unsigned long arg); unsigned long arg);
static int sx_init_drivers(void); static int sx_init_drivers(void);
static struct tty_driver *sx_driver; static struct tty_driver *sx_driver;
...@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = { ...@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
static const struct file_operations sx_fw_fops = { static const struct file_operations sx_fw_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = sx_fw_ioctl, .unlocked_ioctl = sx_fw_ioctl,
}; };
static struct miscdevice sx_fw_device = { static struct miscdevice sx_fw_device = {
...@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max) ...@@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max)
} }
#endif #endif
static int sx_fw_ioctl(struct inode *inode, struct file *filp, static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
unsigned int cmd, unsigned long arg) unsigned long arg)
{ {
int rc = 0; long rc = 0;
int __user *descr = (int __user *)arg; int __user *descr = (int __user *)arg;
int i; int i;
static struct sx_board *board = NULL; static struct sx_board *board = NULL;
...@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, ...@@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
func_enter(); func_enter();
#if 0 if (!capable(CAP_SYS_RAWIO))
/* 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)) {
return -EPERM; return -EPERM;
}
#endif lock_kernel();
sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); 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, ...@@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
for (i = 0; i < SX_NBOARDS; i++) for (i = 0; i < SX_NBOARDS; i++)
sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
unlock_kernel();
return -EIO; return -EIO;
} }
switch (cmd) { switch (cmd) {
case SXIO_SET_BOARD: case SXIO_SET_BOARD:
sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
rc = -EIO;
if (arg >= SX_NBOARDS) if (arg >= SX_NBOARDS)
return -EIO; break;
sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
if (!(boards[arg].flags & SX_BOARD_PRESENT)) if (!(boards[arg].flags & SX_BOARD_PRESENT))
return -EIO; break;
sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
board = &boards[arg]; board = &boards[arg];
rc = 0;
/* FIXME: And this does ... nothing?? */
break; break;
case SXIO_GET_TYPE: case SXIO_GET_TYPE:
rc = -ENOENT; /* If we manage to miss one, return error. */ 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, ...@@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = SX_TYPE_SI; rc = SX_TYPE_SI;
if (IS_EISA_BOARD(board)) if (IS_EISA_BOARD(board))
rc = SX_TYPE_SI; 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; break;
case SXIO_DO_RAMTEST: case SXIO_DO_RAMTEST:
if (sx_initialized) /* Already initialized: better not ramtest the board. */ 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, ...@@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = do_memtest(board, 0, 0x7ff8); rc = do_memtest(board, 0, 0x7ff8);
/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
} }
sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", sx_dprintk(SX_DEBUG_FIRMWARE,
rc); "returning memtest result= %ld\n", rc);
break; break;
case SXIO_DOWNLOAD: case SXIO_DOWNLOAD:
if (sx_initialized) /* Already initialized */ if (sx_initialized) {/* Already initialized */
return -EEXIST; rc = -EEXIST;
if (!sx_reset(board)) break;
return -EIO; }
if (!sx_reset(board)) {
rc = -EIO;
break;
}
sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
if (!tmp) if (!tmp) {
return -ENOMEM; rc = -ENOMEM;
break;
}
/* FIXME: check returns */
get_user(nbytes, descr++); get_user(nbytes, descr++);
get_user(offset, descr++); get_user(offset, descr++);
get_user(data, descr++); get_user(data, descr++);
...@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, ...@@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
(i + SX_CHUNK_SIZE > nbytes) ? (i + SX_CHUNK_SIZE > nbytes) ?
nbytes - i : SX_CHUNK_SIZE)) { nbytes - i : SX_CHUNK_SIZE)) {
kfree(tmp); kfree(tmp);
return -EFAULT; rc = -EFAULT;
break;
} }
memcpy_toio(board->base2 + offset + i, tmp, memcpy_toio(board->base2 + offset + i, tmp,
(i + SX_CHUNK_SIZE > nbytes) ? (i + SX_CHUNK_SIZE > nbytes) ?
...@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, ...@@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = sx_nports; rc = sx_nports;
break; break;
case SXIO_INIT: case SXIO_INIT:
if (sx_initialized) /* Already initialized */ if (sx_initialized) { /* Already initialized */
return -EEXIST; rc = -EEXIST;
break;
}
/* This is not allowed until all boards are initialized... */ /* This is not allowed until all boards are initialized... */
for (i = 0; i < SX_NBOARDS; i++) { for (i = 0; i < SX_NBOARDS; i++) {
if ((boards[i].flags & SX_BOARD_PRESENT) && if ((boards[i].flags & SX_BOARD_PRESENT) &&
!(boards[i].flags & SX_BOARD_INITIALIZED)) !(boards[i].flags & SX_BOARD_INITIALIZED)) {
return -EIO; rc = -EIO;
break;
}
} }
for (i = 0; i < SX_NBOARDS; i++) for (i = 0; i < SX_NBOARDS; i++)
if (!(boards[i].flags & SX_BOARD_PRESENT)) if (!(boards[i].flags & SX_BOARD_PRESENT))
...@@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, ...@@ -1832,10 +1845,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
rc = sx_nports; rc = sx_nports;
break; break;
default: default:
printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", rc = -ENOTTY;
cmd);
break; break;
} }
unlock_kernel();
func_exit(); func_exit();
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment