Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+43 −30
Original line number Diff line number Diff line
@@ -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;
}