[PATCH] driver core: Do not remove the knode driver when autoprobe is disabled
Edward Adam Davis <[email protected]>
| Newsgroups | dev.linux.lists.driver-core,org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb |
|---|---|
| Message-ID | <[email protected]> |
After the user writes 0 to /sys/bus/usb/drivers_autoprobe, the USB device
fails to undergo the probe process, and the user does not manually perform
a bind operation.
Consequently, the corresponding driver is not bound to the device; this
leads to the removal of `dev->p->knode_driver` during driver release upon
usb device disconnection, triggering [1].
Add a check for knode_driver before removing it.
[1]
Oops: general protection fault, probably for non-canonical address 0xdffffc000000000b: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000058-0x000000000000005f]
Call Trace:
klist_del lib/klist.c:230 [inline]
klist_remove+0x14c/0x2e0 lib/klist.c:249
__device_release_driver drivers/base/dd.c:1357 [inline]
device_release_driver_internal+0x4fb/0x620 drivers/base/dd.c:1372
bus_remove_device+0x2bc/0x560 drivers/base/bus.c:664
device_del+0x376/0x9b0 drivers/base/core.c:3961
usb_disable_device+0x367/0x810 drivers/usb/core/message.c:1478
usb_disconnect+0x2e2/0x9a0 drivers/usb/core/hub.c:2345
hub_port_connect drivers/usb/core/hub.c:5415 [inline]
hub_port_connect_change drivers/usb/core/hub.c:5715 [inline]
port_event drivers/usb/core/hub.c:5879 [inline]
hub_event+0x1bb1/0x4420 drivers/usb/core/hub.c:5961
Fixes: 94e7b1c5ff20 ("[PATCH] Add a klist to struct device_driver for the devices bound to it.")
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=87188222c77c0dbbdb4d
Tested-by: [email protected]
Signed-off-by: Edward Adam Davis <[email protected]>
---
drivers/base/dd.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 60c005223844..4154b44990b2 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -1354,7 +1354,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
device_unbind_cleanup(dev);
device_links_driver_cleanup(dev);
- klist_remove(&dev->p->knode_driver);
+ if (device_is_bound(dev))
+ klist_remove(&dev->p->knode_driver);
device_pm_check_callbacks(dev);
bus_notify(dev, BUS_NOTIFY_UNBOUND_DRIVER);
--
2.43.0