ChangeSet 1.893.2.25, 2003/01/06 11:02:15-08:00, [EMAIL PROTECTED]
[PATCH] scanner.c: fix race in ioctl_scanner()
This patch adds locking to ioctl_scanner() which was completely
lacking until now. The patch is originally from Oliver Neukum
<[EMAIL PROTECTED]>.
diff -Nru a/drivers/usb/scanner.c b/drivers/usb/scanner.c
--- a/drivers/usb/scanner.c Mon Jan 6 11:29:32 2003
+++ b/drivers/usb/scanner.c Mon Jan 6 11:29:32 2003
@@ -327,6 +327,8 @@
* - Accept devices with more than one interface. Only use interfaces that
* look like belonging to scanners.
* - Use altsetting[0], not altsetting[ifnum].
+ * - Add locking to ioctl_scanner(). Thanks to Oliver Neukum
+ * <[EMAIL PROTECTED]>.
*
* TODO
* - Remove the 2/3 endpoint limitation
@@ -417,7 +419,7 @@
dev = scn->scn_dev;
- down(&(scn->sem)); /* Now protect the scn_usb_data structure */
+ down(&(scn->sem)); /* Now protect the scn_usb_data structure */
up(&scn_mutex); /* Now handled by the above */
@@ -651,7 +653,7 @@
goto data_recvd;
}
}
-
+
if (result == -EPIPE) { /* No hope */
if(usb_clear_halt(dev, scn->bulk_in_ep)) {
err("read_scanner(%d): Failure to clear endpoint halt
condition (%Zd).", scn_minor, ret);
@@ -699,30 +701,26 @@
ioctl_scanner(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct scn_usb_data *scn;
struct usb_device *dev;
+ int retval = -ENOTTY;
- kdev_t scn_minor;
-
- scn_minor = USB_SCN_MINOR(inode);
-
- if (!p_scn_table[scn_minor]) {
- err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
- return -ENODEV;
- }
+ scn = file->private_data;
+ down(&(scn->sem));
- dev = p_scn_table[scn_minor]->scn_dev;
+ dev = scn->scn_dev;
switch (cmd)
{
case SCANNER_IOCTL_VENDOR :
- return (put_user(dev->descriptor.idVendor, (unsigned int *) arg));
+ retval = (put_user(dev->descriptor.idVendor, (unsigned int *) arg));
+ break;
case SCANNER_IOCTL_PRODUCT :
- return (put_user(dev->descriptor.idProduct, (unsigned int *) arg));
+ retval = (put_user(dev->descriptor.idProduct, (unsigned int *) arg));
+ break;
#ifdef PV8630
case PV8630_IOCTL_INREQUEST :
{
- int result;
-
struct {
__u8 data;
__u8 request;
@@ -730,48 +728,42 @@
__u16 index;
} args;
- if (copy_from_user(&args, (void *)arg, sizeof(args)))
- return -EFAULT;
+ if (copy_from_user(&args, (void *)arg, sizeof(args))) {
+ retval = -EFAULT;
+ break;
+ }
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
args.request, USB_TYPE_VENDOR|
USB_RECIP_DEVICE|USB_DIR_IN,
args.value, args.index, &args.data,
1, HZ*5);
- dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x
args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index,
args.request);
-
if (copy_to_user((void *)arg, &args, sizeof(args)))
- return -EFAULT;
+ retval = -EFAULT;
- dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);
-
- return result;
+ break;
}
case PV8630_IOCTL_OUTREQUEST :
{
- int result;
-
struct {
__u8 request;
__u16 value;
__u16 index;
} args;
- if (copy_from_user(&args, (void *)arg, sizeof(args)))
- return -EFAULT;
-
- dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x
args.request:%x\n", scn_minor, args.value, args.index, args.request);
+ if (copy_from_user(&args, (void *)arg, sizeof(args))) {
+ retval = -EFAULT;
+ break;
+ }
- result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
args.request, USB_TYPE_VENDOR|
USB_RECIP_DEVICE|USB_DIR_OUT,
args.value, args.index, NULL,
0, HZ*5);
- dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);
-
- return result;
+ break;
}
#endif /* PV8630 */
case SCANNER_IOCTL_CTRLMSG:
@@ -782,19 +774,26 @@
} cmsg;
int pipe, nb, ret;
unsigned char buf[64];
-
- if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
- return -EFAULT;
+ retval = 0;
+
+ if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) {
+ retval = -EFAULT;
+ break;
+ }
nb = cmsg.req.wLength;
- if (nb > sizeof(buf))
- return -EINVAL;
+ if (nb > sizeof(buf)) {
+ retval = -EINVAL;
+ break;
+ }
if ((cmsg.req.bRequestType & 0x80) == 0) {
pipe = usb_sndctrlpipe(dev, 0);
- if (nb > 0 && copy_from_user(buf, cmsg.data, nb))
- return -EFAULT;
+ if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) {
+ retval = -EFAULT;
+ break;
+ }
} else {
pipe = usb_rcvctrlpipe(dev, 0);
}
@@ -806,19 +805,21 @@
buf, nb, HZ);
if (ret < 0) {
- err("ioctl_scanner(%d): control_msg returned %d\n", scn_minor,
ret);
- return -EIO;
+ err("ioctl_scanner: control_msg returned %d\n", ret);
+ retval = -EIO;
+ break;
}
if (nb > 0 && (cmsg.req.bRequestType & 0x80) &&
copy_to_user(cmsg.data, buf, nb))
- return -EFAULT;
+ retval = -EFAULT;
- return 0;
+ break;
}
default:
- return -ENOTTY;
+ break;
}
- return 0;
+ up(&(scn->sem));
+ return retval;
}
static struct
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel