[PATCH 21/22] staging: comedi: make determination of read or write subdevice safer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



`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@xxxxxxxxx>
---
 drivers/staging/comedi/comedi_fops.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index d569484..8cb9d95 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;
-- 
1.8.4.2

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux