Skip to content

Commit

Permalink
[PATCH] USB: ub oops in block_uevent
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Pete Zaitcev authored and gregkh committed May 9, 2006
1 parent 436f576 commit 77ef6c4
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions drivers/block/ub.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,9 @@ static void ub_cleanup(struct ub_dev *sc)
kfree(lun);
}

usb_set_intfdata(sc->intf, NULL);
usb_put_intf(sc->intf);
usb_put_dev(sc->dev);
kfree(sc);
}

Expand Down Expand Up @@ -2221,7 +2224,12 @@ static int ub_probe(struct usb_interface *intf,
// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
usb_set_intfdata(intf, sc);
usb_get_dev(sc->dev);
// usb_get_intf(sc->intf); /* Do we need this? */
/*
* Since we give the interface struct to the block level through
* disk->driverfs_dev, we have to pin it. Otherwise, block_uevent
* oopses on close after a disconnect (kernels 2.6.16 and up).
*/
usb_get_intf(sc->intf);

snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
sc->dev->bus->busnum, sc->dev->devnum);
Expand Down Expand Up @@ -2286,7 +2294,7 @@ static int ub_probe(struct usb_interface *intf,

err_dev_desc:
usb_set_intfdata(intf, NULL);
// usb_put_intf(sc->intf);
usb_put_intf(sc->intf);
usb_put_dev(sc->dev);
kfree(sc);
err_core:
Expand Down Expand Up @@ -2461,12 +2469,6 @@ static void ub_disconnect(struct usb_interface *intf)
* and no URBs left in transit.
*/

usb_set_intfdata(intf, NULL);
// usb_put_intf(sc->intf);
sc->intf = NULL;
usb_put_dev(sc->dev);
sc->dev = NULL;

ub_put(sc);
}

Expand Down

0 comments on commit 77ef6c4

Please sign in to comment.