All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chengyu Liu <lui2012qwq@gmail.com>
To: linux-usb@vger.kernel.org
Cc: b-liu@ti.com, gregkh@linuxfoundation.org, nkapron@google.com,
	tony@atomide.com, bigeasy@linutronix.de, balbi@ti.com,
	shimoda.yoshihiro@renesas.com, robert.jarzmik@free.fr,
	Chengyu Liu <lui2012qwq@gmail.com>
Subject: Re: [PATCH v2 0/4] usb: stop timers/works left armed on teardown
Date: Fri, 13 Nov 2026 14:36:14 +0800	[thread overview]
Message-ID: <20261113063614.47540-1-lui2012qwq@gmail.com> (raw)
In-Reply-To: <20261113063409.47485-1-lui2012qwq@gmail.com>

The KASAN report and the reproducer kit for the gpio-vbus instance
[4/4], as promised in the cover letter.  [4/4] is unchanged in v2,
so this is the same report and kit as posted in the v1 thread.

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

      parent reply	other threads:[~2026-11-13  6:36 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13  6:34 [PATCH v2 0/4] usb: stop timers/works left armed on teardown Chengyu Liu
2026-11-13  6:34 ` [PATCH v2 1/4] usb: musb: cancel the delayed works after quiescing the interrupt Chengyu Liu
2026-11-13  6:34 ` [PATCH v2 2/4] usb: musb: dsps: free the VBUS interrupt before the child teardown Chengyu Liu
2026-11-13  6:34 ` [PATCH v2 3/4] usb: gadget: r8a66597: free the IRQ before deleting the timer Chengyu Liu
2026-11-13  6:34 ` [PATCH v2 4/4] usb: phy: gpio-vbus: free the interrupt before cancelling the work Chengyu Liu
2026-11-13  6:36 ` Chengyu Liu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261113063614.47540-1-lui2012qwq@gmail.com \
    --to=lui2012qwq@gmail.com \
    --cc=b-liu@ti.com \
    --cc=balbi@ti.com \
    --cc=bigeasy@linutronix.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=nkapron@google.com \
    --cc=robert.jarzmik@free.fr \
    --cc=shimoda.yoshihiro@renesas.com \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.