Driver core: fix race in __device_release_driver
This patch (as1013) was suggested by David Woodhouse; it fixes a race in the driver core. If a device is unregistered at the same time as its driver is unloaded, the driver's code pages may be unmapped while the remove method is still running. The calls to get_driver() and put_driver() were intended to prevent this, but they don't work if the driver's module count has already dropped to 0. Instead, the patch keeps the device on the driver's list until after the remove method has returned. This forces the necessary synchronization to occur. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
c8e90d822b
Коммит
ef2c51746d
|
@ -289,11 +289,10 @@ static void __device_release_driver(struct device * dev)
|
|||
{
|
||||
struct device_driver * drv;
|
||||
|
||||
drv = get_driver(dev->driver);
|
||||
drv = dev->driver;
|
||||
if (drv) {
|
||||
driver_sysfs_remove(dev);
|
||||
sysfs_remove_link(&dev->kobj, "driver");
|
||||
klist_remove(&dev->knode_driver);
|
||||
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
|
||||
|
@ -306,7 +305,7 @@ static void __device_release_driver(struct device * dev)
|
|||
drv->remove(dev);
|
||||
devres_release_all(dev);
|
||||
dev->driver = NULL;
|
||||
put_driver(drv);
|
||||
klist_remove(&dev->knode_driver);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче