Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] USB: ub oops in block_uevent

In kernel 2.6.16, if a mounted storage device is removed, an oops happens
because ub supplies an interface device (and kobject) to the block layer,
but neglects to pin it. And apparently, the block layer expects its users
to pin device structures.

The code in ub was broken this way for years. But the bug was exposed only
by 2.6.16 when it started to call block_uevent on close, which traverses
device structures (kobjects actually).

Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Pete Zaitcev and committed by
Greg Kroah-Hartman
77ef6c4d 436f5762

+10 -8
+10 -8
drivers/block/ub.c
··· 536 536 kfree(lun); 537 537 } 538 538 539 + usb_set_intfdata(sc->intf, NULL); 540 + usb_put_intf(sc->intf); 541 + usb_put_dev(sc->dev); 539 542 kfree(sc); 540 543 } 541 544 ··· 2224 2221 // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 2225 2222 usb_set_intfdata(intf, sc); 2226 2223 usb_get_dev(sc->dev); 2227 - // usb_get_intf(sc->intf); /* Do we need this? */ 2224 + /* 2225 + * Since we give the interface struct to the block level through 2226 + * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent 2227 + * oopses on close after a disconnect (kernels 2.6.16 and up). 2228 + */ 2229 + usb_get_intf(sc->intf); 2228 2230 2229 2231 snprintf(sc->name, 12, DRV_NAME "(%d.%d)", 2230 2232 sc->dev->bus->busnum, sc->dev->devnum); ··· 2294 2286 2295 2287 err_dev_desc: 2296 2288 usb_set_intfdata(intf, NULL); 2297 - // usb_put_intf(sc->intf); 2289 + usb_put_intf(sc->intf); 2298 2290 usb_put_dev(sc->dev); 2299 2291 kfree(sc); 2300 2292 err_core: ··· 2468 2460 * At this point there must be no commands coming from anyone 2469 2461 * and no URBs left in transit. 2470 2462 */ 2471 - 2472 - usb_set_intfdata(intf, NULL); 2473 - // usb_put_intf(sc->intf); 2474 - sc->intf = NULL; 2475 - usb_put_dev(sc->dev); 2476 - sc->dev = NULL; 2477 2463 2478 2464 ub_put(sc); 2479 2465 }