Commit db658f6b authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

[PATCH] USB: fix race between open() and probe()

registering the device before setting the interface data can lead
to a null pointer being followed in open(). This patch fixes that.
parent 5281f9b7
...@@ -833,22 +833,15 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -833,22 +833,15 @@ static int usblp_probe(struct usb_interface *intf,
init_waitqueue_head(&usblp->wait); init_waitqueue_head(&usblp->wait);
usblp->ifnum = intf->altsetting->desc.bInterfaceNumber; usblp->ifnum = intf->altsetting->desc.bInterfaceNumber;
retval = usb_register_dev(intf, &usblp_class);
if (retval) {
err("Not able to get a minor for this device.");
goto abort;
}
usblp->minor = intf->minor;
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->writeurb) { if (!usblp->writeurb) {
err("out of memory"); err("out of memory");
goto abort_minor; goto abort;
} }
usblp->readurb = usb_alloc_urb(0, GFP_KERNEL); usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->readurb) { if (!usblp->readurb) {
err("out of memory"); err("out of memory");
goto abort_minor; goto abort;
} }
/* Malloc device ID string buffer to the largest expected length, /* Malloc device ID string buffer to the largest expected length,
...@@ -856,7 +849,7 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -856,7 +849,7 @@ static int usblp_probe(struct usb_interface *intf,
* could change in length. */ * could change in length. */
if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) { if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
err("out of memory for device_id_string"); err("out of memory for device_id_string");
goto abort_minor; goto abort;
} }
usblp->writebuf = usblp->readbuf = NULL; usblp->writebuf = usblp->readbuf = NULL;
...@@ -868,19 +861,19 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -868,19 +861,19 @@ static int usblp_probe(struct usb_interface *intf,
if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
GFP_KERNEL, &usblp->writeurb->transfer_dma))) { GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
err("out of memory for write buf"); err("out of memory for write buf");
goto abort_minor; goto abort;
} }
if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
GFP_KERNEL, &usblp->readurb->transfer_dma))) { GFP_KERNEL, &usblp->readurb->transfer_dma))) {
err("out of memory for read buf"); err("out of memory for read buf");
goto abort_minor; goto abort;
} }
/* Allocate buffer for printer status */ /* Allocate buffer for printer status */
usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
if (!usblp->statusbuf) { if (!usblp->statusbuf) {
err("out of memory for statusbuf"); err("out of memory for statusbuf");
goto abort_minor; goto abort;
} }
/* Lookup quirks for this printer. */ /* Lookup quirks for this printer. */
...@@ -894,12 +887,12 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -894,12 +887,12 @@ static int usblp_probe(struct usb_interface *intf,
dbg("incompatible printer-class device 0x%4.4X/0x%4.4X", dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
dev->descriptor.idVendor, dev->descriptor.idVendor,
dev->descriptor.idProduct); dev->descriptor.idProduct);
goto abort_minor; goto abort;
} }
/* Setup the selected alternate setting and endpoints. */ /* Setup the selected alternate setting and endpoints. */
if (usblp_set_protocol(usblp, protocol) < 0) if (usblp_set_protocol(usblp, protocol) < 0)
goto abort_minor; goto abort;
/* Retrieve and store the device ID string. */ /* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp); usblp_cache_device_id_string(usblp);
...@@ -920,10 +913,17 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -920,10 +913,17 @@ static int usblp_probe(struct usb_interface *intf,
usblp->present = 1; usblp->present = 1;
retval = usb_register_dev(intf, &usblp_class);
if (retval) {
err("Not able to get a minor for this device.");
goto abort_intfdata;
}
usblp->minor = intf->minor;
return 0; return 0;
abort_minor: abort_intfdata:
usb_deregister_dev(intf, &usblp_class); usb_set_intfdata (intf, NULL);
abort: abort:
if (usblp) { if (usblp) {
if (usblp->writebuf) if (usblp->writebuf)
......
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