[PATCH 0/1] media: rc: fix igorplugusb disconnect UAF

Yuanzhe Liu posted 1 patch 10 hours ago
drivers/media/rc/igorplugusb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH 0/1] media: rc: fix igorplugusb disconnect UAF
Posted by Yuanzhe Liu 10 hours ago
Hi,

this single-patch series fixes a task_struct use-after-free in the
igorplugusb disconnect path. The crash was observed during USB reset
stress testing of an emulated IgorPlug-USB receiver (03eb:0002) behind
xHCI on a KASAN-enabled 7.1.2 kernel. Real hardware has not been tested.

Root-cause walkthrough
----------------------

1. A control URB completion enters igorplugusb_callback().
2. USBDEVFS_RESET concurrently unbinds the interface and enters
   igorplugusb_disconnect().
3. The disconnect path calls rc_unregister_device() first, which stops
   the raw-IR kthread through ir_raw_event_unregister().
4. The pending callback reaches ir_raw_event_handle() and passes the
   stale raw->thread pointer to wake_up_process(). try_to_wake_up() then
   accesses the freed task_struct while acquiring p->pi_lock.

Patch summary
-------------

Patch 1 poisons and drains the URB, then synchronously deletes the timer,
before unregistering the rc device. This removes both URB producers while
the raw-IR thread is still alive.

Crash report addressed
----------------------

  Report 1: KASAN slab-use-after-free write in try_to_wake_up(), reached
            from igorplugusb_callback() through ir_raw_event_handle().
            A condensed splat is appended below the diffstat.

Test status
-----------

The patch passes git's whitespace check. It has not been build-tested or
runtime-tested, and no Tested-by tag is claimed.

Yuanzhe Liu (1):
  media: rc: igorplugusb: quiesce callbacks before unregister

 drivers/media/rc/igorplugusb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--
Crash excerpt:

  BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0x63/0xb0
  Write of size 4 at addr ffff888004b0732c by task ksoftirqd/0/14

  Call Trace:
   try_to_wake_up+0x80/0x1030 kernel/sched/core.c:4190
   ir_raw_event_handle+0x6a/0x80 drivers/media/rc/rc-ir-raw.c:232
   igorplugusb_irdata drivers/media/rc/igorplugusb.c:70 [inline]
   igorplugusb_callback+0x7c4/0x920 drivers/media/rc/igorplugusb.c:105
   __usb_hcd_giveback_urb+0x236/0x540 drivers/usb/core/hcd.c:1655
   usb_giveback_urb_bh+0x20b/0x530 drivers/usb/core/hcd.c:1689

  Second to last potentially related work creation:
   kthread_stop+0x120/0x240 kernel/kthread.c:760
   ir_raw_event_unregister+0x85/0x2f0 drivers/media/rc/rc-ir-raw.c:662
   rc_unregister_device+0x2e5/0x380 drivers/media/rc/rc-main.c:2022
   igorplugusb_disconnect+0x5e/0x1d0 drivers/media/rc/igorplugusb.c:244
   usb_unbind_interface+0x188/0x770 drivers/usb/core/driver.c:458
   usb_forced_unbind_intf+0xf1/0x1a0 drivers/usb/core/driver.c:1133
   usb_reset_device+0x4c4/0x1db0 drivers/usb/core/hub.c:6404

  The buggy address belongs to the cache task_struct of size 3328.
  It is located 1836 bytes inside a freed 3328-byte region.