| From 284846ea774c7559a8e79918d406ba8a244a20af Mon Sep 17 00:00:00 2001 |
| From: Lukas Wunner <lukas@wunner.de> |
| Date: Wed, 8 Jul 2020 15:27:01 +0200 |
| Subject: [PATCH] driver core: Avoid binding drivers to dead devices |
| |
| commit 654888327e9f655a9d55ad477a9583e90e8c9b5c upstream. |
| |
| Commit 3451a495ef24 ("driver core: Establish order of operations for |
| device_add and device_del via bitflag") sought to prevent asynchronous |
| driver binding to a device which is being removed. It added a |
| per-device "dead" flag which is checked in the following code paths: |
| |
| * asynchronous binding in __driver_attach_async_helper() |
| * synchronous binding in device_driver_attach() |
| * asynchronous binding in __device_attach_async_helper() |
| |
| It did *not* check the flag upon: |
| |
| * synchronous binding in __device_attach() |
| |
| However __device_attach() may also be called asynchronously from: |
| |
| deferred_probe_work_func() |
| bus_probe_device() |
| device_initial_probe() |
| __device_attach() |
| |
| So if the commit's intention was to check the "dead" flag in all |
| asynchronous code paths, then a check is also necessary in |
| __device_attach(). Add the missing check. |
| |
| Fixes: 3451a495ef24 ("driver core: Establish order of operations for device_add and device_del via bitflag") |
| Signed-off-by: Lukas Wunner <lukas@wunner.de> |
| Cc: stable@vger.kernel.org # v5.1+ |
| Cc: Alexander Duyck <alexander.h.duyck@linux.intel.com> |
| Link: https://lore.kernel.org/r/de88a23a6fe0ef70f7cfd13c8aea9ab51b4edab6.1594214103.git.lukas@wunner.de |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/base/dd.c b/drivers/base/dd.c |
| index 98c1d471a8eb..432a6f52cadb 100644 |
| --- a/drivers/base/dd.c |
| +++ b/drivers/base/dd.c |
| @@ -819,7 +819,9 @@ static int __device_attach(struct device *dev, bool allow_async) |
| int ret = 0; |
| |
| device_lock(dev); |
| - if (dev->driver) { |
| + if (dev->p->dead) { |
| + goto out_unlock; |
| + } else if (dev->driver) { |
| if (device_is_bound(dev)) { |
| ret = 1; |
| goto out_unlock; |
| -- |
| 2.27.0 |
| |