Commit c8d50986 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Greg Kroah-Hartman

driver core: Fix DL_FLAG_AUTOREMOVE_SUPPLIER device link flag handling

Change the list walk in device_links_driver_cleanup() to a safe one
to avoid use-after-free when dropping a link from the list during the
walk.

Also, while at it, fix device_link_add() to refuse to create
stateless device links with DL_FLAG_AUTOREMOVE_SUPPLIER set, which is
an invalid combination (setting that flag means that the driver core
should manage the link, so it cannot be stateless), and extend the
kerneldoc comment of device_link_add() to cover the
DL_FLAG_AUTOREMOVE_SUPPLIER flag properly too.

Fixes: 1689cac5 ("driver core: Add flag to autoremove device link on supplier unbind")
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8d84b18f
...@@ -179,10 +179,14 @@ void device_pm_move_to_tail(struct device *dev) ...@@ -179,10 +179,14 @@ void device_pm_move_to_tail(struct device *dev)
* of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be * of the link. If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be
* ignored. * ignored.
* *
* If the DL_FLAG_AUTOREMOVE_CONSUMER is set, the link will be removed * If the DL_FLAG_AUTOREMOVE_CONSUMER flag is set, the link will be removed
* automatically when the consumer device driver unbinds from it. * automatically when the consumer device driver unbinds from it. Analogously,
* The combination of both DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_STATELESS * if DL_FLAG_AUTOREMOVE_SUPPLIER is set in @flags, the link will be removed
* set is invalid and will cause NULL to be returned. * automatically when the supplier device driver unbinds from it.
*
* The combination of DL_FLAG_STATELESS and either DL_FLAG_AUTOREMOVE_CONSUMER
* or DL_FLAG_AUTOREMOVE_SUPPLIER set in @flags at the same time is invalid and
* will cause NULL to be returned upfront.
* *
* A side effect of the link creation is re-ordering of dpm_list and the * A side effect of the link creation is re-ordering of dpm_list and the
* devices_kset list by moving the consumer device and all devices depending * devices_kset list by moving the consumer device and all devices depending
...@@ -199,8 +203,8 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -199,8 +203,8 @@ struct device_link *device_link_add(struct device *consumer,
struct device_link *link; struct device_link *link;
if (!consumer || !supplier || if (!consumer || !supplier ||
((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_STATELESS &&
(flags & DL_FLAG_AUTOREMOVE_CONSUMER))) flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER)))
return NULL; return NULL;
device_links_write_lock(); device_links_write_lock();
...@@ -539,11 +543,11 @@ void device_links_no_driver(struct device *dev) ...@@ -539,11 +543,11 @@ void device_links_no_driver(struct device *dev)
*/ */
void device_links_driver_cleanup(struct device *dev) void device_links_driver_cleanup(struct device *dev)
{ {
struct device_link *link; struct device_link *link, *ln;
device_links_write_lock(); device_links_write_lock();
list_for_each_entry(link, &dev->links.consumers, s_node) { list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) {
if (link->flags & DL_FLAG_STATELESS) if (link->flags & DL_FLAG_STATELESS)
continue; continue;
......
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