Skip to content

Commit 2eeae47

Browse files
name2965gregkh
authored andcommitted
media: as102: fix to not free memory after the device is registered in as102_usb_probe()
commit 8bd29db upstream. In as102_usb driver, the following race condition occurs: ``` CPU0 CPU1 as102_usb_probe() kzalloc(); // alloc as102_dev_t .... usb_register_dev(); fd = sys_open("/path/to/dev"); // open as102 fd .... usb_deregister_dev(); .... kfree(); // free as102_dev_t .... sys_close(fd); as102_release() // UAF!! as102_usb_release() kfree(); // DFB!! ``` When a USB character device registered with usb_register_dev() is later unregistered (via usb_deregister_dev() or disconnect), the device node is removed so new open() calls fail. However, file descriptors that are already open do not go away immediately: they remain valid until the last reference is dropped and the driver's .release() is invoked. In as102, as102_usb_probe() calls usb_register_dev() and then, on an error path, does usb_deregister_dev() and frees as102_dev_t right away. If userspace raced a successful open() before the deregistration, that open FD will later hit as102_release() --> as102_usb_release() and access or free as102_dev_t again, occur a race to use-after-free and double-free vuln. The fix is to never kfree(as102_dev_t) directly once usb_register_dev() has succeeded. After deregistration, defer freeing memory to .release(). In other words, let release() perform the last kfree when the final open FD is closed. Cc: <[email protected]> Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=47321e8fd5a4c84088db Fixes: cd19f7d ("[media] as102: fix leaks at failure paths in as102_usb_probe()") Signed-off-by: Jeongjun Park <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1c52ef0 commit 2eeae47

1 file changed

Lines changed: 2 additions & 0 deletions

File tree

drivers/media/usb/as102/as102_usb_drv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,9 @@ static int as102_usb_probe(struct usb_interface *intf,
403403
failed_dvb:
404404
as102_free_usb_stream_buffer(as102_dev);
405405
failed_stream:
406+
usb_set_intfdata(intf, NULL);
406407
usb_deregister_dev(intf, &as102_usb_class_driver);
408+
return ret;
407409
failed:
408410
usb_put_dev(as102_dev->bus_adap.usb_dev);
409411
usb_set_intfdata(intf, NULL);

0 commit comments

Comments
 (0)