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);