summaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/comedi_fops.c
diff options
context:
space:
mode:
authorIan Abbott2013-11-08 16:03:42 +0100
committerGreg Kroah-Hartman2013-11-12 01:16:45 +0100
commit63ab039511509739f881acfb99aef76b772e35a2 (patch)
tree0405ce8c45c3c7c3feabd050f0f6e250e772e8e5 /drivers/staging/comedi/comedi_fops.c
parentstaging: comedi: remove comedi_dev_from_minor() (diff)
downloadkernel-qcow2-linux-63ab039511509739f881acfb99aef76b772e35a2.tar.gz
kernel-qcow2-linux-63ab039511509739f881acfb99aef76b772e35a2.tar.xz
kernel-qcow2-linux-63ab039511509739f881acfb99aef76b772e35a2.zip
staging: comedi: make determination of read or write subdevice safer
`comedi_read_subdevice()` and `comedi_write_subdevice()` respectively determine the read and write subdevice to use for a comedi device, depending on a minor device number passed in. The comedi device has a main "board" minor device number and may also have dynamically assigned, subdevice-specific minor device numbers, in a range of numbers shared by all comedi devices. If the minor device number is within the range of subdevice-specific minor device numbers, both functions call `comedi_subdevice_from_minor()` to determine what subdevice is associated with the minor device number (if any) and then check the subdevice belongs to the comedi device. Since the subdevice might belong to a different comedi device, the check is not protected against the subdevice being freed. Perform the check in `comedi_subdevice_from_minor()` instead, where it is protected against the subdevice being freed. Make it return `NULL` if the subdevice does not belong to the device. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/comedi_fops.c')
-rw-r--r--drivers/staging/comedi/comedi_fops.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index d569484f315b..8cb9d956e8f2 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -177,7 +177,7 @@ static void comedi_free_board_dev(struct comedi_device *dev)
}
static struct comedi_subdevice
-*comedi_subdevice_from_minor(unsigned minor)
+*comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned minor)
{
struct comedi_subdevice *s;
unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
@@ -185,6 +185,8 @@ static struct comedi_subdevice
BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS);
mutex_lock(&comedi_subdevice_minor_table_lock);
s = comedi_subdevice_minor_table[i];
+ if (s && s->device != dev)
+ s = NULL;
mutex_unlock(&comedi_subdevice_minor_table_lock);
return s;
}
@@ -229,10 +231,8 @@ comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor)
struct comedi_subdevice *s;
if (minor >= COMEDI_NUM_BOARD_MINORS) {
- s = comedi_subdevice_from_minor(minor);
- if (!s || s->device != dev)
- return NULL;
- if (s->subdev_flags & SDF_CMD_READ)
+ s = comedi_subdevice_from_minor(dev, minor);
+ if (s == NULL || (s->subdev_flags & SDF_CMD_READ))
return s;
}
return dev->read_subdev;
@@ -244,10 +244,8 @@ comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
struct comedi_subdevice *s;
if (minor >= COMEDI_NUM_BOARD_MINORS) {
- s = comedi_subdevice_from_minor(minor);
- if (!s || s->device != dev)
- return NULL;
- if (s->subdev_flags & SDF_CMD_WRITE)
+ s = comedi_subdevice_from_minor(dev, minor);
+ if (s == NULL || (s->subdev_flags & SDF_CMD_WRITE))
return s;
}
return dev->write_subdev;