[PATCH v3 1/2] usbip: usbip_host: fix null pointer dereference in rebind_store
Jeffin Philip <[email protected]>
| Newsgroups | org.kernel.vger.linux-usb,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
rebind_store drops locks to execute do_rebind which sleeps during which time udev may become NULL due to physical disconnect. Since this cannot be prevented and spinlocks cannot be obtained in do_rebind, we turn towards the function that performs the same action, drivers_probe, safely. Remove rebind_store and print a warning to the user to use drivers_probe instead as a safer alternative. Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=af76b01c9a0f0ab60fb0 Fixes: 4bfb141bc013 ("usbip: usbip_host: fix to hold parent lock for device_attach() calls") Cc: [email protected] Signed-off-by: Jeffin Philip <[email protected]> --- Changes in v3: - Addressed the race condition proposed by Greg KH in v2 discussion. Changes in v2: - Addressed concerns raised by the Greg KH in v1 discussion - Added usb_get_dev() to get a reference to udev preventing it from becoming null after the null check. Drop the reference after using it in do_rebind() v1: - Initial patch with a udev null check that returns -ENODEV if udev is null. --- drivers/usb/usbip/stub_main.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c index 79110a69d697..013f1563b1e9 100644 --- a/drivers/usb/usbip/stub_main.c +++ b/drivers/usb/usbip/stub_main.c @@ -242,32 +242,7 @@ static void stub_device_rebind(void) static ssize_t rebind_store(struct device_driver *dev, const char *buf, size_t count) { - int ret; - int len; - struct bus_id_priv *bid; - - /* buf length should be less that BUSID_SIZE */ - len = strnlen(buf, BUSID_SIZE); - - if (!(len < BUSID_SIZE)) - return -EINVAL; - - bid = get_busid_priv(buf); - if (!bid) - return -ENODEV; - - /* mark the device for deletion so probe ignores it during rescan */ - bid->status = STUB_BUSID_OTHER; - /* release the busid lock */ - put_busid_priv(bid); - - ret = do_rebind((char *) buf, bid); - if (ret < 0) - return ret; - - /* delete device from busid_table */ - del_match_busid((char *) buf); - + pr_warn("rebind node is deprecated, consider using drivers_probe instead\n"); return count; } -- 2.55.0