Re: WARNING in usbhid_raw_request/usb_submit_urb

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Aug 13, 2019 at 10:13 PM Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
>
> On Mon, 12 Aug 2019, syzbot wrote:
>
> > Hello,
> >
> > syzbot has tested the proposed patch but the reproducer still triggered
> > crash:
> > KASAN: invalid-free in hcd_buffer_free
>
> This bug report shows that Hillf's fix isn't exactly right.
>
> > usb 5-1: USB disconnect, device number 2
> > ==================================================================
> > BUG: KASAN: double-free or invalid-free in hcd_buffer_free+0x199/0x260
> > drivers/usb/core/buffer.c:165
> >
> > CPU: 0 PID: 1745 Comm: kworker/0:2 Not tainted 5.3.0-rc2+ #1
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
> > Google 01/01/2011
> > Workqueue: usb_hub_wq hub_event
> > Call Trace:
> >   __dump_stack lib/dump_stack.c:77 [inline]
> >   dump_stack+0xca/0x13e lib/dump_stack.c:113
> >   print_address_description+0x6a/0x32c mm/kasan/report.c:351
> >   kasan_report_invalid_free+0x61/0xa0 mm/kasan/report.c:444
> >   __kasan_slab_free+0x162/0x180 mm/kasan/common.c:428
> >   slab_free_hook mm/slub.c:1423 [inline]
> >   slab_free_freelist_hook mm/slub.c:1470 [inline]
> >   slab_free mm/slub.c:3012 [inline]
> >   kfree+0xe4/0x2f0 mm/slub.c:3953
> >   hcd_buffer_free+0x199/0x260 drivers/usb/core/buffer.c:165
> >   usb_free_coherent+0x67/0x80 drivers/usb/core/usb.c:932
> >   hid_free_buffers.isra.0+0x94/0x290 drivers/hid/usbhid/hid-core.c:964
> >   usbhid_stop+0x308/0x450 drivers/hid/usbhid/hid-core.c:1224
> >   logi_dj_remove+0x107/0x210 drivers/hid/hid-logitech-dj.c:1797
>
> Here the double-free occurred when logi_dj_remove() called
> hd_hw_stop()...
>
> >   hid_device_remove+0xed/0x240 drivers/hid/hid-core.c:2242
> >   __device_release_driver drivers/base/dd.c:1118 [inline]
> >   device_release_driver_internal+0x206/0x4c0 drivers/base/dd.c:1151
> >   bus_remove_device+0x2dc/0x4a0 drivers/base/bus.c:556
> >   device_del+0x420/0xb10 drivers/base/core.c:2288
> >   hid_remove_device drivers/hid/hid-core.c:2413 [inline]
> >   hid_destroy_device+0xe1/0x150 drivers/hid/hid-core.c:2432
> >   usbhid_disconnect+0xad/0xd0 drivers/hid/usbhid/hid-core.c:1414
>
> which occurred inside usbhid_disconnect()'s call to
> hid_destroy_device().
>
> But just above the call to hid_destroy_device(), Hillf's patch adds a
> direct call to hid_hw_stop(), which is what did the original free.
>
> So it looks like the problem here is that some paths in the original
> unpatched code end up calling hid_hw_stop() by way of the hid_device's
> driver, and other paths do not.
>
> I haven't had time to track down this difference.  Maybe somebody
> on the mailing list already knows why it occurs.

Trying Alan's fix from another thread here:

#syz test: https://github.com/google/kasan.git 7f7867ff
Index: usb-devel/drivers/hid/hid-lg.c
===================================================================
--- usb-devel.orig/drivers/hid/hid-lg.c
+++ usb-devel/drivers/hid/hid-lg.c
@@ -818,7 +818,7 @@ static int lg_probe(struct hid_device *h
 
 		if (!buf) {
 			ret = -ENOMEM;
-			goto err_free;
+			goto err_stop;
 		}
 
 		ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(cbuf),
@@ -850,9 +850,12 @@ static int lg_probe(struct hid_device *h
 		ret = lg4ff_init(hdev);
 
 	if (ret)
-		goto err_free;
+		goto err_stop;
 
 	return 0;
+
+err_stop:
+	hid_hw_stop(hdev);
 err_free:
 	kfree(drv_data);
 	return ret;
@@ -863,8 +866,7 @@ static void lg_remove(struct hid_device
 	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
 	if (drv_data->quirks & LG_FF4)
 		lg4ff_deinit(hdev);
-	else
-		hid_hw_stop(hdev);
+	hid_hw_stop(hdev);
 	kfree(drv_data);
 }
 
Index: usb-devel/drivers/hid/hid-lg4ff.c
===================================================================
--- usb-devel.orig/drivers/hid/hid-lg4ff.c
+++ usb-devel/drivers/hid/hid-lg4ff.c
@@ -1477,7 +1477,6 @@ int lg4ff_deinit(struct hid_device *hid)
 		}
 	}
 #endif
-	hid_hw_stop(hid);
 	drv_data->device_props = NULL;
 
 	kfree(entry);


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux