Commit 3abd0aea authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] raw driver: cleanups and small fixes

- There was an unchecked bdget().  bdget can fail due to ENOMEM.

- rework the error handling implementation in raw_ctl_ioctl().

- Replace MOD_INC_USE_COUNT with try_module_get(THIS_MODULE).  This allows
  the raw module to be unloaded again.

  The core kernel has already taken a ref on the module prior to entering
  the ioctl, so try_module_get() cannot fail.
parent 9e0acd29
......@@ -122,13 +122,12 @@ raw_ioctl(struct inode *inode, struct file *filp,
* Deal with ioctls against the raw-device control interface, to bind
* and unbind other raw devices.
*/
static int
raw_ctl_ioctl(struct inode *inode, struct file *filp,
static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
unsigned int command, unsigned long arg)
{
struct raw_config_request rq;
struct raw_device_data *rawdev;
int err;
int err = 0;
switch (command) {
case RAW_SETBIND:
......@@ -136,13 +135,15 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp,
/* First, find out which raw minor we want */
if (copy_from_user(&rq, (void *) arg, sizeof(rq))) {
err = -EFAULT;
if (copy_from_user(&rq, (void *) arg, sizeof(rq)))
goto out;
}
if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) {
err = -EINVAL;
if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS)
goto out;
}
rawdev = &raw_devices[rq.raw_minor];
if (command == RAW_SETBIND) {
......@@ -152,9 +153,10 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp,
* This is like making block devices, so demand the
* same capability
*/
if (!capable(CAP_SYS_ADMIN)) {
err = -EPERM;
if (!capable(CAP_SYS_ADMIN))
goto out;
}
/*
* For now, we don't need to check that the underlying
......@@ -163,17 +165,18 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp,
* major/minor numbers make sense.
*/
err = -EINVAL;
dev = MKDEV(rq.block_major, rq.block_minor);
if ((rq.block_major == 0 && rq.block_minor != 0) ||
MAJOR(dev) != rq.block_major ||
MINOR(dev) != rq.block_minor)
MINOR(dev) != rq.block_minor) {
err = -EINVAL;
goto out;
}
down(&raw_mutex);
err = -EBUSY;
if (rawdev->inuse) {
up(&raw_mutex);
err = -EBUSY;
goto out;
}
if (rawdev->binding) {
......@@ -185,7 +188,10 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp,
rawdev->binding = NULL;
} else {
rawdev->binding = bdget(dev);
MOD_INC_USE_COUNT;
if (rawdev->binding == NULL)
err = -ENOMEM;
else
try_module_get(THIS_MODULE);
}
up(&raw_mutex);
} else {
......@@ -200,13 +206,12 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp,
rq.block_major = rq.block_minor = 0;
}
up(&raw_mutex);
if (copy_to_user((void *)arg, &rq, sizeof(rq))) {
err = -EFAULT;
if (copy_to_user((void *)arg, &rq, sizeof(rq)))
goto out;
}
err = 0;
}
break;
default:
err = -EINVAL;
break;
......
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