* [PATCH 0/4] usb: stop timers/works left armed on teardown
@ 2026-11-12 16:04 Chengyu Liu
2026-11-12 16:04 ` [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove() Chengyu Liu
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Chengyu Liu @ 2026-11-12 16:04 UTC (permalink / raw)
To: linux-usb
Cc: b-liu, gregkh, nkapron, tony, bigeasy, balbi, shimoda.yoshihiro,
robert.jarzmik, Chengyu Liu
The teardown paths in these four drivers do not quiesce every producer
of asynchronous work before draining it: an interrupt handler may still
queue or re-arm a timer or work item after the cancellation, while the
corresponding object is being torn down. In three of them the IRQ is
devm-managed and freed only at detach, after remove() returns; in musb
the plain free_irq() happens later in the same remove path. Either way
a late interrupt re-arms the callback, which then runs on freed memory:
[1/4] musb core: musb_stage0_irq() can schedule irq_work while
handling stage-0 USB interrupts, and the work can also re-arm
itself from the session recheck path; musb_remove() cancels it
before masking the interrupts and before free_irq().
[2/4] musb dsps glue: the devm VBUS interrupt outlives the child
teardown that deletes musb->dev_timer; its handler re-arms
the timer via dsps_mod_timer().
[3/4] r8a66597: r8a66597_remove() deletes the timer while the devm
IRQ can still re-arm it from the VBINT path.
[4/4] gpio-vbus: gpio_vbus_remove() cancels the work while the devm
GPIO interrupt can still re-arm it (100 ms debounce delay).
Two further instances of this defect class found in the same sweep -
pch_udc and lpc32xx_udc - are being handled in Hyunjung Ko's
"usb: gadget: pch_udc: drain vbus GPIO works before freeing the
device" and "usb: gadget: lpc32xx_udc: drain the pullup work on
removal" threads, so they are not part of this series.
Testing:
[1-3/4] build-tested on x86_64 (COMPILE_TEST where needed); they
require hardware we do not have, so no runtime reproducer.
[4/4] additionally confirmed with a KASAN reproducer: the driver
probed on a gpio-sim chip in QEMU, slab-use-after-free write
in __run_timer_base() after unregister (5/5 runs), clean with
the fix (0/5). The KASAN report and the reproducer kit follow
in this thread.
All found by static analysis. Fixes written with AI assistance.
Chengyu Liu (4):
usb: musb: cancel irq_work after masking interrupts in musb_remove()
usb: musb: dsps: free the VBUS interrupt before the child teardown
usb: gadget: r8a66597: free the IRQ before deleting the timer
usb: phy: gpio-vbus: free the interrupt before cancelling the work
drivers/usb/gadget/udc/r8a66597-udc.c | 8 ++++++++
drivers/usb/gadget/udc/r8a66597-udc.h | 1 +
drivers/usb/musb/musb_core.c | 10 +++++++++-
drivers/usb/musb/musb_dsps.c | 11 +++++++++++
drivers/usb/phy/phy-gpio-vbus-usb.c | 8 ++++++++
5 files changed, 37 insertions(+), 1 deletion(-)
Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
--
2.25.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove()
2026-11-12 16:04 [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
@ 2026-11-12 16:04 ` Chengyu Liu
2026-11-12 16:23 ` sashiko-bot
2026-11-12 16:04 ` [PATCH 2/4] usb: musb: dsps: free the VBUS interrupt before the child teardown Chengyu Liu
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Chengyu Liu @ 2026-11-12 16:04 UTC (permalink / raw)
To: linux-usb
Cc: b-liu, gregkh, nkapron, tony, bigeasy, balbi, shimoda.yoshihiro,
robert.jarzmik, Chengyu Liu, stable
musb_stage0_irq() can schedule irq_work while handling stage-0 USB
interrupts, and the work can also re-arm itself from the session
recheck path (musb_pm_runtime_check_session()). musb_remove()
cancels irq_work while the interrupt is still enabled and the IRQ
line not yet freed: an interrupt landing after the cancel re-arms
the work, and musb_irq_work() then runs after musb_free() has
released the struct.
Move the cancel behind musb_disable_interrupts() and synchronize the
IRQ line first, so no handler can be running or re-arm the work past
the cancel.
Found by static analysis.
Fixes: c5340bd14336 ("usb: musb: cancel work on removal")
Cc: stable@vger.kernel.org
Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
---
Build-tested on x86_64: musb_core.o compiles clean
(USB_MUSB_HDRC). No runtime reproducer: requires MUSB-based OTG
hardware. Fix written with AI assistance.
drivers/usb/musb/musb_core.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 9b63b56edc45..eea43a20a1d0 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2630,7 +2630,6 @@ static void musb_remove(struct platform_device *pdev)
*/
musb_exit_debugfs(musb);
- cancel_delayed_work_sync(&musb->irq_work);
cancel_delayed_work_sync(&musb->finish_resume_work);
cancel_delayed_work_sync(&musb->deassert_reset_work);
pm_runtime_get_sync(musb->controller);
@@ -2642,6 +2641,15 @@ static void musb_remove(struct platform_device *pdev)
musb_disable_interrupts(musb);
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
spin_unlock_irqrestore(&musb->lock, flags);
+
+ /*
+ * musb_stage0_irq() arms irq_work, so it can only be cancelled
+ * for good once interrupts are masked and any in-flight handler
+ * has completed.
+ */
+ synchronize_irq(musb->nIrq);
+ cancel_delayed_work_sync(&musb->irq_work);
+
musb_platform_exit(musb);
pm_runtime_dont_use_autosuspend(musb->controller);
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] usb: musb: dsps: free the VBUS interrupt before the child teardown
2026-11-12 16:04 [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
2026-11-12 16:04 ` [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove() Chengyu Liu
@ 2026-11-12 16:04 ` Chengyu Liu
2026-11-12 16:04 ` [PATCH 3/4] usb: gadget: r8a66597: free the IRQ before deleting the timer Chengyu Liu
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Chengyu Liu @ 2026-11-12 16:04 UTC (permalink / raw)
To: linux-usb
Cc: b-liu, gregkh, nkapron, tony, bigeasy, balbi, shimoda.yoshihiro,
robert.jarzmik, Chengyu Liu, stable
dsps_remove() unregisters the musb child, which deletes
musb->dev_timer and frees the structure, while the glue's VBUS
interrupt is devm-managed and only freed after dsps_remove() returns.
dsps_vbus_threaded_irq() re-arms the timer via dsps_mod_timer(), so
a VBUS event in between re-arms dev_timer past its deletion and
otg_timer() runs on freed memory.
Free the VBUS interrupt first, which also waits for any in-flight
handler, so nothing can re-arm the timer once the child teardown
runs.
Found by static analysis.
Fixes: 369469a92393 ("usb: musb: Add support for optional VBUS irq to dsps glue layer")
Cc: stable@vger.kernel.org
Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
---
Build-tested on x86_64: musb_dsps.o compiles clean
(USB_MUSB_DSPS). No runtime reproducer: requires AM33xx/DSPS
hardware. Fix written with AI assistance.
drivers/usb/musb/musb_dsps.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 91d8712efa41..69c8b4b3ffa7 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -942,6 +942,17 @@ static void dsps_remove(struct platform_device *pdev)
{
struct dsps_glue *glue = platform_get_drvdata(pdev);
+ /*
+ * The VBUS interrupt handler re-arms musb->dev_timer via
+ * dsps_mod_timer(); the IRQ is devm-managed and would only be
+ * freed after this function returns, while the child teardown
+ * below deletes the timer and frees the musb structure. Free
+ * the interrupt first so no VBUS event can re-arm the timer
+ * past that point.
+ */
+ if (glue->vbus_irq)
+ devm_free_irq(glue->dev, glue->vbus_irq, glue);
+
platform_device_unregister(glue->musb);
pm_runtime_disable(&pdev->dev);
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] usb: gadget: r8a66597: free the IRQ before deleting the timer
2026-11-12 16:04 [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
2026-11-12 16:04 ` [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove() Chengyu Liu
2026-11-12 16:04 ` [PATCH 2/4] usb: musb: dsps: free the VBUS interrupt before the child teardown Chengyu Liu
@ 2026-11-12 16:04 ` Chengyu Liu
2026-11-12 16:18 ` sashiko-bot
2026-11-12 16:04 ` [PATCH 4/4] usb: phy: gpio-vbus: free the interrupt before cancelling the work Chengyu Liu
2026-11-12 16:10 ` [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
4 siblings, 1 reply; 10+ messages in thread
From: Chengyu Liu @ 2026-11-12 16:04 UTC (permalink / raw)
To: linux-usb
Cc: b-liu, gregkh, nkapron, tony, bigeasy, balbi, shimoda.yoshihiro,
robert.jarzmik, Chengyu Liu, stable
r8a66597_remove() deletes r8a66597->timer while the interrupt is
still live: the IRQ is devm-managed and only freed at detach, and
r8a66597_irq() re-arms the timer when sampling VBUS (VBINT). An
interrupt landing after timer_delete_sync() re-arms the timer, and
r8a66597_timer() then runs on freed memory.
Store the requested IRQ number at probe time and free it before
deleting the timer; freeing also waits for any running handler, so
nothing can re-arm the timer past the delete.
Found by static analysis.
Fixes: c41442474a26 ("usb: gadget: R8A66597 peripheral controller support.")
Cc: stable@vger.kernel.org
Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
---
Build-tested on x86_64: r8a66597-udc.o compiles clean
(USB_R8A66597 + COMPILE_TEST). No runtime reproducer: requires
R8A66597 hardware. Fix written with AI assistance.
drivers/usb/gadget/udc/r8a66597-udc.c | 8 ++++++++
drivers/usb/gadget/udc/r8a66597-udc.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index 469075b064ba..bfccc6565e0a 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1810,6 +1810,13 @@ static void r8a66597_remove(struct platform_device *pdev)
struct r8a66597 *r8a66597 = platform_get_drvdata(pdev);
usb_del_gadget_udc(&r8a66597->gadget);
+
+ /*
+ * The interrupt handler re-arms the timer on VBUS changes; the
+ * IRQ is devm-managed and freed only at detach, so free it
+ * before deleting the timer.
+ */
+ devm_free_irq(&pdev->dev, r8a66597->irq, r8a66597);
timer_delete_sync(&r8a66597->timer);
r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
@@ -1896,6 +1903,7 @@ static int r8a66597_probe(struct platform_device *pdev)
udc_name, r8a66597);
if (ret < 0)
goto clean_up2;
+ r8a66597->irq = irq;
INIT_LIST_HEAD(&r8a66597->gadget.ep_list);
r8a66597->gadget.ep0 = &r8a66597->ep[0].ep;
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.h b/drivers/usb/gadget/udc/r8a66597-udc.h
index 9a115caba661..08acabe02421 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.h
+++ b/drivers/usb/gadget/udc/r8a66597-udc.h
@@ -110,6 +110,7 @@ struct r8a66597 {
unsigned char interrupt;
unsigned char isochronous;
unsigned char num_dma;
+ int irq;
unsigned irq_sense_low:1;
};
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] usb: phy: gpio-vbus: free the interrupt before cancelling the work
2026-11-12 16:04 [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
` (2 preceding siblings ...)
2026-11-12 16:04 ` [PATCH 3/4] usb: gadget: r8a66597: free the IRQ before deleting the timer Chengyu Liu
@ 2026-11-12 16:04 ` Chengyu Liu
2026-11-12 16:16 ` sashiko-bot
2026-11-12 16:10 ` [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
4 siblings, 1 reply; 10+ messages in thread
From: Chengyu Liu @ 2026-11-12 16:04 UTC (permalink / raw)
To: linux-usb
Cc: b-liu, gregkh, nkapron, tony, bigeasy, balbi, shimoda.yoshihiro,
robert.jarzmik, Chengyu Liu, stable
gpio_vbus_remove() cancels gpio_vbus->work while the VBUS sensing GPIO
interrupt is still live: it is devm-managed and freed only at detach,
and gpio_vbus_irq() schedules the work with a 100 ms debounce delay.
A plug event landing after the cancel re-arms the work, and its timer
then fires on the freed gpio_vbus_data.
Free the interrupt first, which also waits for any running handler,
so nothing can re-arm the work past the cancel.
Found by static analysis and confirmed with a KASAN reproducer:
slab-use-after-free write in __run_timer_base() within one debounce
interval of unregistering the device while its VBUS GPIO is toggled
(object allocated by gpio_vbus_probe() via devm_kmalloc(), freed by
devres_release_all() at unbind).
Fixes: c2344f13b59e ("USB: gpio_vbus: add delayed vbus_session calls")
Cc: stable@vger.kernel.org
Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
---
The reproducer instantiates the unmodified driver on a gpio-sim
chip in QEMU and toggles the line while the device is unregistered;
it widens the remove()-to-detach window with a 500 ms sleep, logic
otherwise unmodified. Repeated runs: 5/5 KASAN splats without the
fix, 0/5 with it. The KASAN report and the reproducer kit follow
in this thread. Also build-tested on x86_64 (USB_GPIO_VBUS).
Fix written with AI assistance.
drivers/usb/phy/phy-gpio-vbus-usb.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 60b7c1219dd2..82d2301c3804 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -325,6 +325,14 @@ static void gpio_vbus_remove(struct platform_device *pdev)
struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
device_init_wakeup(&pdev->dev, 0);
+
+ /*
+ * The VBUS sensing GPIO interrupt is devm-managed and freed only
+ * at detach, and its handler schedules the work with a 100ms
+ * delay; free the interrupt before cancelling the work so a
+ * late plug event cannot re-arm it past the cancel.
+ */
+ devm_free_irq(&pdev->dev, gpio_vbus->irq, pdev);
cancel_delayed_work_sync(&gpio_vbus->work);
usb_remove_phy(&gpio_vbus->phy);
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/4] usb: stop timers/works left armed on teardown
2026-11-12 16:04 [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
` (3 preceding siblings ...)
2026-11-12 16:04 ` [PATCH 4/4] usb: phy: gpio-vbus: free the interrupt before cancelling the work Chengyu Liu
@ 2026-11-12 16:10 ` Chengyu Liu
4 siblings, 0 replies; 10+ messages in thread
From: Chengyu Liu @ 2026-11-12 16:10 UTC (permalink / raw)
To: linux-usb
Cc: b-liu, gregkh, nkapron, tony, bigeasy, balbi, shimoda.yoshihiro,
robert.jarzmik, Chengyu Liu
The KASAN report and the reproducer kit for the gpio-vbus instance
[4/4], as promised in the cover letter.
Environment: QEMU x86_64, generic KASAN kernel (v7.3-rc7 plus unrelated
local commits; config: KASAN/KASAN_GENERIC=y, GPIOLIB=y, GPIO_SIM=y,
CONFIGFS_FS=y, USB_GADGET=m, USB_GPIO_VBUS=m),
phy-gpio-vbus-usb built as a module. The driver under test is
unmodified except for the disclosed 500 ms sleep widening the
remove()-to-detach window.
Setup: a one-line gpio-sim chip labelled "vbus-sim" stands in for the
VBUS sense GPIO; writing its "pull" sysfs attribute generates real GPIO
edge interrupts. The vbus_rig module registers a gpiod lookup table and
the "gpio-vbus" platform device, so the real driver probes it, and
attaches a dummy usb_gadget to phy->otg->gadget so gpio_vbus_irq() takes
its normal schedule_delayed_work() path (a UDC provides this on real
hardware); the module fails to load if the phy cannot be attached, so a
clean run cannot be a setup artifact. rmmod vbus_rig runs the real
gpio_vbus_remove() while the line is being toggled.
Results over repeated runs of the same script:
vulnerable kernel: 5/5 runs, KASAN slab-use-after-free each time
patched kernel: 5/5 runs, clean
Representative vulnerable splat (VBUS edges toggle at max rate while the
device is unregistered; an interrupt lands after the
cancel_delayed_work_sync(), re-arms the 100 ms debounce work, and the
work's timer fires after the devm release has freed gpio_vbus_data):
[ 3.571772] BUG: KASAN: slab-use-after-free in __run_timer_base.part.0+0x80c/0x900
[ 3.571779] Write of size 8 at addr ffff8880033291d8 by task sh/89
[ 3.571781]
[ 3.571784] CPU: 0 UID: 0 PID: 89 Comm: sh Tainted: G W O 7.3.0-rc7-00036-gf9532d351e12-dirty #29 PREEMPT(lazy)
[ 3.571788] Tainted: [W]=WARN, [O]=OOT_MODULE
[ 3.571788] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
[ 3.571790] Call Trace:
[ 3.571791] <IRQ>
[ 3.571792] dump_stack_lvl+0x55/0x70
[ 3.571808] print_report+0x10d/0x5d0
[ 3.571811] ? __run_timer_base.part.0+0x80c/0x900
[ 3.571813] kasan_report+0x96/0xd0
[ 3.571815] ? __run_timer_base.part.0+0x80c/0x900
[ 3.571817] __run_timer_base.part.0+0x80c/0x900
[ 3.571819] ? __pfx___run_timer_base.part.0+0x10/0x10
[ 3.571821] ? __pfx___hrtimer_get_next_event+0x10/0x10
[ 3.571825] ? kvm_clock_read+0x15/0x30
[ 3.571827] ? __hrtimer_run_queues+0x2aa/0x580
[ 3.571829] ? clockevents_program_event+0x2b0/0x7c0
[ 3.571833] ? hrtimer_update_next_event+0x8a/0x100
[ 3.571835] run_timer_softirq+0xd6/0x190
[ 3.571837] handle_softirqs+0x184/0x5c0
[ 3.571840] ? __hrtimer_rearm_deferred+0x15d/0x460
[ 3.571841] irq_exit_rcu+0x6e/0x150
[ 3.571843] sysvec_apic_timer_interrupt+0x70/0x80
[ 3.571845] </IRQ>
[ 3.571846] <TASK>
[ 3.571846] asm_sysvec_apic_timer_interrupt+0x1a/0x20
[ 3.571849] RIP: 0010:stack_depot_save_flags+0x61/0x830
[ 3.571852] Code: 70 05 05 00 74 16 48 83 c4 30 44 89 e8 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 89 c1 48 01 c9 89 cf 8d 04 8d 7b 71 f5 75 <83> f9 03 0f 86 36 01 00 00 89 c3 89 c1 4c 89 fe 03 5e 08 03 06 83
[ 3.571854] RSP: 0018:ffff888002207a08 EFLAGS: 00000216
[ 3.571856] RAX: 0000000075f571cb RBX: ffff888003880988 RCX: 0000000000000014
[ 3.571858] RDX: ffffffffb3000130 RSI: 000000000000000a RDI: 0000000000000014
[ 3.571859] RBP: ffff888001041640 R08: 0000000000000000 R09: ffffffffb87baec6
[ 3.571859] R10: ffff888002207978 R11: ffff888002207f50 R12: 0000000000000001
[ 3.571860] R13: 0000000000000000 R14: 000000000000000a R15: ffff888002207a70
[ 3.571862] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 3.571864] ? stack_depot_save_flags+0x2d/0x830
[ 3.571866] ? kernfs_fop_write_iter+0x168/0x480
[ 3.571868] kasan_save_stack+0x34/0x50
[ 3.571870] ? kasan_save_stack+0x24/0x50
[ 3.571871] ? kasan_save_track+0x14/0x30
[ 3.571872] ? kasan_save_free_info+0x3a/0x60
[ 3.571874] ? __kasan_slab_free+0x43/0x70
[ 3.571875] ? kfree+0x18e/0x3c0
[ 3.571877] ? kernfs_fop_write_iter+0x168/0x480
[ 3.571878] ? vfs_write+0x87a/0xd40
[ 3.571880] ? ksys_write+0xf3/0x1c0
[ 3.571881] ? do_syscall_64+0xee/0x500
[ 3.571883] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 3.571885] ? do_sys_openat2+0x308/0x450
[ 3.571886] ? kasan_save_stack+0x34/0x50
[ 3.571888] ? kasan_save_stack+0x24/0x50
[ 3.571889] ? kasan_save_track+0x14/0x30
[ 3.571890] ? kasan_save_free_info+0x3a/0x60
[ 3.571892] ? __kasan_slab_free+0x43/0x70
[ 3.571893] ? kmem_cache_free+0x1d4/0x3c0
[ 3.571895] ? do_sys_openat2+0x308/0x450
[ 3.571896] ? do_sys_open+0x8d/0xe0
[ 3.571898] ? __x64_sys_openat+0x9d/0x110
[ 3.571899] ? do_syscall_64+0xee/0x500
[ 3.571901] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 3.571902] ? __pfx_path_openat+0x10/0x10
[ 3.571905] ? kasan_save_stack+0x34/0x50
[ 3.571906] ? kasan_save_stack+0x24/0x50
[ 3.571907] ? mutex_unlock+0x82/0xd0
[ 3.571909] ? __pfx_mutex_unlock+0x10/0x10
[ 3.571911] ? _raw_spin_lock_irqsave+0x8b/0xf0
[ 3.571913] ? gpio_sim_apply_pull+0x1c8/0x4e0
[ 3.571915] ? __pfx_gpio_sim_apply_pull+0x10/0x10
[ 3.571917] ? kasan_save_track+0x14/0x30
[ 3.571918] kasan_save_track+0x14/0x30
[ 3.571920] kasan_save_free_info+0x3a/0x60
[ 3.571921] __kasan_slab_free+0x43/0x70
[ 3.571923] kfree+0x18e/0x3c0
[ 3.571925] ? __pfx_sysfs_kf_write+0x10/0x10
[ 3.571926] kernfs_fop_write_iter+0x168/0x480
[ 3.571928] vfs_write+0x87a/0xd40
[ 3.571929] ? alloc_fd+0x2c6/0x5d0
[ 3.571932] ? __pfx_vfs_write+0x10/0x10
[ 3.571933] ? __do_sys_wait4+0xf2/0x100
[ 3.571935] ? fdget_pos+0x1cd/0x4c0
[ 3.571937] ksys_write+0xf3/0x1c0
[ 3.571939] ? __pfx_ksys_write+0x10/0x10
[ 3.571940] do_syscall_64+0xee/0x500
[ 3.571942] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 3.571944] RIP: 0033:0x49a227
[ 3.571945] Code: 64 89 02 48 c7 c0 ff ff ff ff eb bb 0f 1f 80 00 00 00 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24
[ 3.571947] RSP: 002b:00007ffd89cad1e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[ 3.571948] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 000000000049a227
[ 3.571949] RDX: 000000000000000a RSI: 000000003e0afe50 RDI: 0000000000000001
[ 3.571951] RBP: 000000003e0afe50 R08: 000000003e0afe50 R09: 006e776f642d6c6c
[ 3.571952] R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000000a
[ 3.571953] R13: 000000003e0ad8a0 R14: 0000000000609c01 R15: 00007ffd89cad250
[ 3.571955] </TASK>
[ 3.571955]
[ 3.571956] Allocated by task 86:
[ 3.571957] kasan_save_stack+0x24/0x50
[ 3.571959] kasan_save_track+0x14/0x30
[ 3.571960] __kasan_kmalloc+0x7f/0x90
[ 3.571961] __kmalloc_node_track_caller_noprof+0x1d4/0x4a0
[ 3.571963] devm_kmalloc+0x81/0x240
[ 3.571965] gpio_vbus_probe+0x30/0x670 [phy_gpio_vbus_usb]
[ 3.571968] platform_probe+0x9e/0x140
[ 3.571970] really_probe+0x1cf/0x5c0
[ 3.571972] __driver_probe_device+0x1a1/0x3b0
[ 3.571974] driver_probe_device+0x49/0xd0
[ 3.571975] __device_attach_driver+0x183/0x200
[ 3.571977] bus_for_each_drv+0x105/0x190
[ 3.571979] __device_attach+0x20b/0x380
[ 3.571981] device_initial_probe+0x7d/0xa0
[ 3.571982] bus_probe_device+0x5a/0x130
[ 3.571983] device_add+0xd6f/0x14c0
[ 3.571984] platform_device_add+0x253/0x5a0
[ 3.571986] platform_device_register_full+0x3c3/0x560
[ 3.571988] 0xffffffffc02250aa
[ 3.571989] do_one_initcall+0x89/0x350
[ 3.571990] do_init_module+0x2a1/0x890
[ 3.571992] load_module+0x5166/0x6750
[ 3.571994] init_module_from_file+0x162/0x190
[ 3.571996] idempotent_init_module+0x325/0x680
[ 3.571997] __x64_sys_finit_module+0xc2/0x130
[ 3.571999] do_syscall_64+0xee/0x500
[ 3.572001] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 3.572002]
[ 3.572002] Freed by task 91:
[ 3.572003] kasan_save_stack+0x24/0x50
[ 3.572004] kasan_save_track+0x14/0x30
[ 3.572005] kasan_save_free_info+0x3a/0x60
[ 3.572007] __kasan_slab_free+0x43/0x70
[ 3.572008] kfree+0x18e/0x3c0
[ 3.572009] release_nodes+0xbe/0x120
[ 3.572011] devres_release_all+0x127/0x1a0
[ 3.572012] device_unbind_cleanup+0x76/0x260
[ 3.572014] device_release_driver_internal+0x163/0x210
[ 3.572015] bus_remove_device+0x256/0x3e0
[ 3.572017] device_del+0x3a8/0x960
[ 3.572019] platform_device_del.part.0+0x1f/0x1e0
[ 3.572020] platform_device_unregister+0x20/0x40
[ 3.572022] 0xffffffffc022008c
[ 3.572023] __x64_sys_delete_module+0x32c/0x4a0
[ 3.572025] do_syscall_64+0xee/0x500
[ 3.572026] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 3.572027]
[ 3.572028] Last potentially related work creation:
[ 3.572028] kasan_save_stack+0x24/0x50
[ 3.572029] kasan_record_aux_stack+0x89/0xa0
[ 3.572031] insert_work+0x2d/0x240
[ 3.572033] __queue_work+0x44e/0xd70
[ 3.572034] call_timer_fn+0x27/0x210
[ 3.572035] __run_timer_base.part.0+0x3cc/0x900
[ 3.572037] run_timer_softirq+0xd6/0x190
[ 3.572039] handle_softirqs+0x184/0x5c0
[ 3.572040] irq_exit_rcu+0x6e/0x150
[ 3.572041] sysvec_apic_timer_interrupt+0x70/0x80
[ 3.572042] asm_sysvec_apic_timer_interrupt+0x1a/0x20
[ 3.572044]
[ 3.572044] Second to last potentially related work creation:
[ 3.572045] kasan_save_stack+0x24/0x50
[ 3.572046] kasan_record_aux_stack+0x89/0xa0
[ 3.572047] insert_work+0x2d/0x240
[ 3.572048] __queue_work+0x44e/0xd70
[ 3.572050] call_timer_fn+0x27/0x210
[ 3.572051] __run_timer_base.part.0+0x3cc/0x900
[ 3.572052] run_timer_softirq+0xd6/0x190
[ 3.572054] handle_softirqs+0x184/0x5c0
[ 3.572055] irq_exit_rcu+0x6e/0x150
[ 3.572056] sysvec_apic_timer_interrupt+0x39/0x80
[ 3.572058] asm_sysvec_apic_timer_interrupt+0x1a/0x20
[ 3.572059]
[ 3.572059] The buggy address belongs to the object at ffff888003329000
[ 3.572059] which belongs to the cache kmalloc-1k of size 1024
[ 3.572061] The buggy address is located 472 bytes inside of
[ 3.572061] freed 1024-byte region [ffff888003329000, ffff888003329400)
[ 3.572062]
[ 3.572063] The buggy address belongs to the physical page:
[ 3.572064] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888003328000 pfn:0x3328
[ 3.572066] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 3.572067] flags: 0x100000000000240(workingset|head|node=0|zone=1)
[ 3.572069] page_type: f5(slab)
[ 3.572071] raw: 0100000000000240 ffff888001041dc0 ffff888001040590 ffffea0000110610
[ 3.572073] raw: ffff888003328000 000000000010000f 00000000f5000000 0000000000000000
[ 3.572075] head: 0100000000000240 ffff888001041dc0 ffff888001040590 ffffea0000110610
[ 3.572076] head: ffff888003328000 000000000010000f 00000000f5000000 0000000000000000
[ 3.572077] head: 0100000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
[ 3.572078] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
[ 3.572078] page dumped because: kasan: bad access detected
[ 3.572079]
[ 3.572079] Memory state around the buggy address:
[ 3.572080] ffff888003329080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3.572081] ffff888003329100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3.572082] >ffff888003329180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3.572083] ^
[ 3.572084] ffff888003329200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3.572084] ffff888003329280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3.572085] ==================================================================
(The "gpiod_get_value can_sleep" WARNINGs earlier in the boot are a
gpio-sim artifact - simulated chips set can_sleep - and are unrelated
to the bug. One of the five runs faulted in gpio_vbus_work() itself
instead of __run_timer_base(); same object, same free site.)
Reproducer kit (against the KASAN kernel tree above):
vbus_rig.c:
// SPDX-License-Identifier: GPL-2.0
/*
* vbus_rig - PoC rig for the gpio-vbus teardown UAF (F-138).
*
* Instantiates a "gpio-vbus" platform device wired via a gpiod lookup
* table to line 0 of a gpio-sim chip labelled "vbus-sim", so the real
* phy-gpio-vbus-usb platform driver probes it. Attaches a dummy
* usb_gadget to phy->otg->gadget so the driver's IRQ handler takes its
* normal schedule_delayed_work() path (it skips scheduling when no
* gadget is attached - on real hardware a UDC provides the gadget).
* rmmod vbus_rig runs the real gpio_vbus_remove() path. Contains no
* vulnerable logic itself.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio/machine.h>
#include <linux/usb/phy.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
static struct gpiod_lookup_table vbus_lookup = {
.dev_id = "gpio-vbus.0",
.table = {
GPIO_LOOKUP("vbus-sim", 0, "vbus", GPIO_ACTIVE_HIGH),
{ }
},
};
static const struct usb_gadget_ops vbus_rig_gadget_ops; /* all NULL */
static struct usb_gadget vbus_rig_gadget = {
.ops = (struct usb_gadget_ops *)&vbus_rig_gadget_ops,
.name = "vbus_rig",
};
static struct platform_device *vbus_pdev;
static struct usb_phy *rig_phy;
static int __init vbus_rig_init(void)
{
gpiod_add_lookup_table(&vbus_lookup);
vbus_pdev = platform_device_register_simple("gpio-vbus", 0, NULL, 0);
if (IS_ERR(vbus_pdev)) {
gpiod_remove_lookup_table(&vbus_lookup);
return PTR_ERR(vbus_pdev);
}
rig_phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR(rig_phy)) {
pr_err("vbus_rig: no phy found (%ld) - setup broken\n",
PTR_ERR(rig_phy));
goto fail;
}
if (!rig_phy->otg) {
pr_err("vbus_rig: phy has no otg - setup broken\n");
usb_put_phy(rig_phy);
goto fail;
}
rig_phy->otg->gadget = &vbus_rig_gadget;
pr_info("vbus_rig: gpio-vbus.0 registered, phy attached\n");
return 0;
fail:
platform_device_unregister(vbus_pdev);
gpiod_remove_lookup_table(&vbus_lookup);
return -ENODEV;
}
static void __exit vbus_rig_exit(void)
{
/*
* Drop our phy reference first; the driver module stays put via
* the bound device. Keep the gadget attached across the
* unregister: the driver's IRQ handler must keep taking its
* normal schedule_delayed_work() path all the way through
* remove().
*/
usb_put_phy(rig_phy);
platform_device_unregister(vbus_pdev);
gpiod_remove_lookup_table(&vbus_lookup);
pr_info("vbus_rig: gpio-vbus.0 unregistered\n");
}
module_init(vbus_rig_init);
module_exit(vbus_rig_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("gpio-vbus teardown UAF PoC rig");
Makefile:
obj-m += vbus_rig.o
guest init script (packed into a busybox initramfs with udc-core.ko,
phy-gpio-vbus-usb.ko and vbus_rig.ko):
#!/bin/sh
# PoC init: gpio-vbus teardown re-arm UAF (F-138)
#
# mode=vuln : kernel has the unpatched gpio_vbus_remove() + a 500ms
# POC-WITNESS msleep() after cancel_delayed_work_sync().
# mode=fixed : kernel has the fix (devm_free_irq before the cancel)
# plus the same witness sleep.
#
# A busy toggler flips the gpio-sim line pull (= VBUS edges) while
# rmmod runs the real remove path. In vuln mode an edge lands after
# the cancel, re-arms the 100ms debounce work, and the work fires on
# the freed gpio_vbus_data -> KASAN slab-use-after-free.
#
# The toggler prints nothing; the console between "rmmod starts" and
# the verdict carries only kernel output. If a run comes out clean,
# just run it again (IRQ delivery timing varies).
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs dev /dev
mount -t configfs none /sys/kernel/config
# 1. one-line gpio-sim chip labelled "vbus-sim"
SIM=/sys/kernel/config/gpio-sim/sim0
mkdir -p $SIM/bank0
echo vbus-sim > $SIM/bank0/label
echo 1 > $SIM/bank0/num_lines
echo 1 > $SIM/live
PULL=$(echo /sys/devices/platform/gpio-sim.0/gpiochip*/sim_gpio0/pull)
# 2. load the gadget core, the real driver + rig (probe runs now)
insmod /udc-core.ko || { echo "SETUP FAIL: udc-core"; poweroff -f; }
insmod /phy-gpio-vbus-usb.ko || { echo "SETUP FAIL: phy module"; poweroff -f; }
insmod /vbus_rig.ko || { echo "SETUP FAIL: rig (phy attach broken)"; poweroff -f; }
ls /sys/bus/platform/drivers/gpio-vbus/
grep -i vbus /proc/interrupts || { echo "SETUP FAIL: no vbus irq"; poweroff -f; }
# 3. toggle VBUS edges at max rate, then run the real remove path
( while :; do echo pull-up > $PULL; echo pull-down > $PULL; done ) &
T=$!
sleep 1
echo "=== rmmod vbus_rig: remove path ==="
rmmod vbus_rig
sleep 2
kill $T
# 4. verdict
if dmesg | grep -q 'BUG: KASAN'; then
echo "=== RESULT: KASAN SPLAT (vuln confirmed) ==="
else
echo "=== RESULT: clean (no KASAN splat) ==="
fi
poweroff -f
run.sh (QEMU wrapper; its first argument is only a log label, the
vulnerable/fixed state comes from which witness diff was applied at
build time):
#!/bin/bash
# run.sh -- boot the PoC in QEMU. usage: run.sh <label> [logfile]
#
# NOTE: <label> is only a name for the log; it does NOT switch kernel
# state. The vulnerable/fixed state comes from which witness diff is
# applied to the kernel tree when the modules and initramfs were last
# built (see README.md: vuln = witness-vuln.diff, fixed =
# witness-fixed.diff).
set -o pipefail
cd "$(dirname "$0")"
K=${KDIR:-$HOME/patternmine/worktrees/vm-hdlc}
MODE=${1:-vuln}
LOG=${2:-/tmp/f138-$MODE.log}
timeout 120 qemu-system-x86_64 -enable-kvm -cpu host -smp 2 -m 1024 \
-kernel "$K/arch/x86/boot/bzImage" \
-initrd initramfs.cpio \
-append "console=ttyS0 loglevel=8 panic_on_oops=0" \
-nographic -no-reboot 2>&1 | tee "$LOG"
matrix.sh (repeated runs):
#!/bin/bash
# matrix.sh -- run N VMs with the current build, print the tally.
# usage: matrix.sh <N> <label> (label is only for log naming; the
# vulnerable/fixed state comes from which witness diff was applied at
# build time -- see README.md)
cd "$(dirname "$0")"
N=${1:-5}
MODE=${2:-vuln}
HIT=0
for i in $(seq 1 "$N"); do
./run.sh "$MODE" "/tmp/f138-matrix-$MODE-$i.log" >/dev/null 2>&1
if grep -q 'BUG: KASAN' "/tmp/f138-matrix-$MODE-$i.log"; then
HIT=$((HIT+1))
elif grep -q 'SETUP FAIL' "/tmp/f138-matrix-$MODE-$i.log"; then
echo "run $i: SETUP FAIL - do not count"; continue
fi
echo "run $i: $(grep -m1 'RESULT' "/tmp/f138-matrix-$MODE-$i.log" | sed 's/.*=== //;s/ ===//')"
done
echo "== $MODE: $HIT/$N KASAN splats =="
witness diff applied to the vulnerable kernel (window widening only,
logic unchanged):
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index ce09e789afd8..f3e1c3f3b125 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -332,6 +332,12 @@ static void gpio_vbus_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
cancel_delayed_work_sync(&gpio_vbus->work);
+ /* POC-WITNESS: widen the re-arm window so the reproducer's
+ * interrupt lands reliably between the cancel and the devm
+ * release. Not part of the bug; logic unchanged.
+ */
+ msleep(500);
+
usb_remove_phy(&gpio_vbus->phy);
}
and for the patched control run, the fix plus the same window:
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index ce09e789afd8..25e0dcd36b34 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -330,8 +330,15 @@ static void gpio_vbus_remove(struct platform_device *pdev)
struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
device_init_wakeup(&pdev->dev, 0);
+
+ devm_free_irq(&pdev->dev, gpio_vbus->irq, pdev);
cancel_delayed_work_sync(&gpio_vbus->work);
+ /* POC-WITNESS: same artificial window as the vuln run, to show
+ * the fix closes it.
+ */
+ msleep(500);
+
usb_remove_phy(&gpio_vbus->phy);
}
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 4/4] usb: phy: gpio-vbus: free the interrupt before cancelling the work
2026-11-12 16:04 ` [PATCH 4/4] usb: phy: gpio-vbus: free the interrupt before cancelling the work Chengyu Liu
@ 2026-11-12 16:16 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-12 16:16 UTC (permalink / raw)
To: Chengyu Liu, linux-usb
> gpio_vbus_remove() cancels gpio_vbus->work while the VBUS sensing GPIO
> interrupt is still live: it is devm-managed and freed only at detach,
> and gpio_vbus_irq() schedules the work with a 100 ms debounce delay.
> A plug event landing after the cancel re-arms the work, and its timer
> then fires on the freed gpio_vbus_data.
>
> Free the interrupt first, which also waits for any running handler,
> so nothing can re-arm the work past the cancel.
>
> Found by static analysis and confirmed with a KASAN reproducer:
> slab-use-after-free write in __run_timer_base() within one debounce
> interval of unregistering the device while its VBUS GPIO is toggled
> (object allocated by gpio_vbus_probe() via devm_kmalloc(), freed by
> devres_release_all() at unbind).
>
> Fixes: c2344f13b59e ("USB: gpio_vbus: add delayed vbus_session calls")
> Cc: stable@vger.kernel.org
> Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112160448.41566-1-lui2012qwq@gmail.com?part=4
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 3/4] usb: gadget: r8a66597: free the IRQ before deleting the timer
2026-11-12 16:04 ` [PATCH 3/4] usb: gadget: r8a66597: free the IRQ before deleting the timer Chengyu Liu
@ 2026-11-12 16:18 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-12 16:18 UTC (permalink / raw)
To: Chengyu Liu, linux-usb
> r8a66597_remove() deletes r8a66597->timer while the interrupt is
> still live: the IRQ is devm-managed and only freed at detach, and
> r8a66597_irq() re-arms the timer when sampling VBUS (VBINT). An
> interrupt landing after timer_delete_sync() re-arms the timer, and
> r8a66597_timer() then runs on freed memory.
>
> Store the requested IRQ number at probe time and free it before
> deleting the timer; freeing also waits for any running handler, so
> nothing can re-arm the timer past the delete.
>
> Found by static analysis.
>
> Fixes: c41442474a26 ("usb: gadget: R8A66597 peripheral controller support.")
> Cc: stable@vger.kernel.org
> Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112160448.41566-1-lui2012qwq@gmail.com?part=3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove()
2026-11-12 16:04 ` [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove() Chengyu Liu
@ 2026-11-12 16:23 ` sashiko-bot
2026-11-12 16:33 ` Chengyu Liu
0 siblings, 1 reply; 10+ messages in thread
From: sashiko-bot @ 2026-11-12 16:23 UTC (permalink / raw)
To: Chengyu Liu, linux-usb
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Low] usb: musb: inaccurate Fixes trailer in commit message for
musb_remove()
--
commit e08f859cc70a9eed1b7e88c3628f7b1178dcabc5
Author: Chengyu Liu <lui2012qwq@gmail.com>
> usb: musb: cancel irq_work after masking interrupts in musb_remove()
>
> musb_stage0_irq() can schedule irq_work while handling stage-0 USB
> interrupts, and the work can also re-arm itself from the session
> recheck path (musb_pm_runtime_check_session()). musb_remove()
> cancels irq_work while the interrupt is still enabled and the IRQ
> line not yet freed: an interrupt landing after the cancel re-arms
> the work, and musb_irq_work() then runs after musb_free() has
> released the struct.
>
> Move the cancel behind musb_disable_interrupts() and synchronize the
> IRQ line first, so no handler can be running or re-arm the work past
> the cancel.
>
> Found by static analysis.
>
> Fixes: c5340bd14336 ("usb: musb: cancel work on removal")
> Cc: stable@vger.kernel.org
> Signed-off-by: Chengyu Liu <lui2012qwq@gmail.com>
[Severity: Low]
In c5340bd14336 ("usb: musb: cancel work on removal"), cancel_work_sync()
was placed in musb_free() immediately after free_irq() and after
musb_shutdown() had disabled interrupts. 66fadea5b79c ("usb: musb: only
cancel work if it is initialized") later moved the cancel into
musb_remove() ahead of free_irq(), and f730f205cc51 ("usb: musb: Split PM
runtime between wrapper IP and musb core") moved it ahead of
musb_disable_interrupts().
Should the Fixes: tag reference f730f205cc51 ("usb: musb: Split PM runtime
between wrapper IP and musb core") instead?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261112160448.41566-1-lui2012qwq@gmail.com?part=1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove()
2026-11-12 16:23 ` sashiko-bot
@ 2026-11-12 16:33 ` Chengyu Liu
0 siblings, 0 replies; 10+ messages in thread
From: Chengyu Liu @ 2026-11-12 16:33 UTC (permalink / raw)
To: sashiko-reviews; +Cc: linux-usb
Thanks, f730f205cc51 is the right one. I'll carry the corrected Fixes
tag if the series needs a respin.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-11-12 16:34 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 16:04 [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
2026-11-12 16:04 ` [PATCH 1/4] usb: musb: cancel irq_work after masking interrupts in musb_remove() Chengyu Liu
2026-11-12 16:23 ` sashiko-bot
2026-11-12 16:33 ` Chengyu Liu
2026-11-12 16:04 ` [PATCH 2/4] usb: musb: dsps: free the VBUS interrupt before the child teardown Chengyu Liu
2026-11-12 16:04 ` [PATCH 3/4] usb: gadget: r8a66597: free the IRQ before deleting the timer Chengyu Liu
2026-11-12 16:18 ` sashiko-bot
2026-11-12 16:04 ` [PATCH 4/4] usb: phy: gpio-vbus: free the interrupt before cancelling the work Chengyu Liu
2026-11-12 16:16 ` sashiko-bot
2026-11-12 16:10 ` [PATCH 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox