Skip to content

Commit

Permalink
driver core: fix shutdown races with probe/remove(v3)
Browse files Browse the repository at this point in the history
Firstly, .shutdown callback may touch a uninitialized hardware
if dev->driver is set and .probe is not completed.

Secondly, device_shutdown() may dereference a null pointer to cause
oops when dev->driver is cleared after it has been checked in
device_shutdown().

So just hold device lock and its parent lock(if it has) to
fix the races.

Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Ming Lei authored and Greg Kroah-Hartman committed Jul 17, 2012
1 parent 6fbfd05 commit d1c6c03
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,13 @@ void device_shutdown(void)
while (!list_empty(&devices_kset->list)) {
dev = list_entry(devices_kset->list.prev, struct device,
kobj.entry);

/*
* hold reference count of device's parent to
* prevent it from being freed because parent's
* lock is to be held
*/
get_device(dev->parent);
get_device(dev);
/*
* Make sure the device is off the kset list, in the
Expand All @@ -1820,6 +1827,11 @@ void device_shutdown(void)
list_del_init(&dev->kobj.entry);
spin_unlock(&devices_kset->list_lock);

/* hold lock to avoid race with probe/release */
if (dev->parent)
device_lock(dev->parent);
device_lock(dev);

/* Don't allow any more runtime suspends */
pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev);
Expand All @@ -1831,7 +1843,13 @@ void device_shutdown(void)
dev_dbg(dev, "shutdown\n");
dev->driver->shutdown(dev);
}

device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);

put_device(dev);
put_device(dev->parent);

spin_lock(&devices_kset->list_lock);
}
Expand Down

0 comments on commit d1c6c03

Please sign in to comment.