Linux USB
 help / color / mirror / Atom feed
From: Cen Zhang <zzzccc427@gmail.com>
To: Valentina Manea <valentina.manea.m@gmail.com>,
	Shuah Khan <shuah@kernel.org>
Cc: Hongren Zheng <i@zenithal.me>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	baijiaju1990@gmail.com
Subject: [BUG] usbip: vhci-hcd: status sysfs read races with HCD teardown
Date: Tue, 23 Jun 2026 11:16:09 +0800	[thread overview]
Message-ID: <20260623031609.138269-1-zzzccc427@gmail.com> (raw)

Hi,

I hit a KASAN use-after-free in usbip vhci-hcd when reading the vhci
status sysfs file while the vhci platform device is being rebound through
the driver core test-remove path.

VHCI exposes sysfs files under:

  /sys/devices/platform/vhci_hcd.0/

The status callback can walk VHCI controller state, including the shared
SuperSpeed HCD.  In the teardown path, the shared HCD can be removed and
put before the sysfs group is withdrawn, leaving a window where
status_show() can dereference freed HCD state.

Observed report:

  BUG: KASAN: slab-use-after-free in _raw_spin_lock+0x30/0x40
  Read of size 1 at addr ffff8880095f4478 by task cat/554

  CPU: 0 UID: 0 PID: 554 Comm: cat Not tainted
  7.1.0-rc2-00375-g917719c412c4 #3 PREEMPT(lazy)

  Call Trace:
   <TASK>
   dump_stack_lvl+0x66/0xa0
   print_report+0xce/0x630
   ? _raw_spin_lock+0x30/0x40
   ? srso_alias_return_thunk+0x5/0xfbef5
   ? __virt_addr_valid+0x188/0x320
   ? _raw_spin_lock+0x30/0x40
   kasan_report+0xe0/0x110
   ? _raw_spin_lock+0x30/0x40
   ? _raw_spin_lock+0x30/0x40
   __kasan_check_byte+0x36/0x50
   lock_acquire+0x11f/0x300
   ? status_show+0x2cb/0x3d0
   ? srso_alias_return_thunk+0x5/0xfbef5
   ? lock_release+0xc8/0x290
   ? __asan_memcpy+0x3c/0x60
   _raw_spin_lock+0x30/0x40
   ? status_show+0x320/0x3d0
   status_show+0x320/0x3d0
   ? __pfx_status_show+0x10/0x10
   ? __pfx_status_show+0x10/0x10
   ? dev_attr_show+0x24/0x90
   dev_attr_show+0x3b/0x90
   sysfs_kf_seq_show+0x115/0x1a0
   ? __pfx_dev_attr_show+0x10/0x10
   seq_read_iter+0x29d/0x790
   vfs_read+0x406/0x590
   ? __pfx_vfs_read+0x10/0x10
   ksys_read+0xd2/0x170
   ? __pfx_ksys_read+0x10/0x10
   ? srso_alias_return_thunk+0x5/0xfbef5
   ? srso_alias_return_thunk+0x5/0xfbef5
   do_syscall_64+0x115/0x6a0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f
   </TASK>

  Allocated by task 545:
   kasan_save_stack+0x33/0x60
   kasan_save_track+0x14/0x30
   __kasan_kmalloc+0x8f/0xa0
   __kmalloc_noprof+0x28f/0x760
   __usb_create_hcd+0x45/0x500
   vhci_hcd_probe+0xd9/0x250
   platform_probe+0x69/0xe0
   really_probe+0x163/0x660
   __driver_probe_device+0x106/0x240
   device_driver_attach+0x7d/0x110
   bind_store+0x95/0xe0
   kernfs_fop_write_iter+0x1e0/0x280
   vfs_write+0x469/0x810
   ksys_write+0xd2/0x170
   do_syscall_64+0x115/0x6a0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f

  Freed by task 545:
   kasan_save_stack+0x33/0x60
   kasan_save_track+0x14/0x30
   kasan_save_free_info+0x3b/0x60
   __kasan_slab_free+0x43/0x70
   kfree+0x315/0x540
   vhci_hcd_remove+0x66/0xc0
   really_probe+0x316/0x660
   __driver_probe_device+0x106/0x240
   device_driver_attach+0x7d/0x110
   bind_store+0x95/0xe0
   kernfs_fop_write_iter+0x1e0/0x280
   vfs_write+0x469/0x810
   ksys_write+0xd2/0x170
   do_syscall_64+0x115/0x6a0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f

  Last potentially related work creation:
   kasan_save_stack+0x33/0x60
   kasan_record_aux_stack+0x8c/0xa0
   __queue_work+0x661/0xa90
   queue_work_on+0x5f/0xb0
   unlink1+0x210/0x220
   usb_hcd_unlink_urb+0xb8/0x120
   usb_kill_urb.part.0+0x96/0x1c0
   hub_quiesce+0xfa/0x160
   hub_suspend+0x292/0x4f0
   usb_suspend_both+0x170/0x4c0
   usb_runtime_suspend+0x30/0x90
   __rpm_callback+0x67/0x290
   rpm_callback+0xab/0xc0
   rpm_suspend+0x1c2/0x970
   __pm_runtime_suspend+0x3d/0x1d0
   usb_new_device+0x645/0x870
   register_root_hub+0x146/0x320
   usb_add_hcd+0x726/0xbd0
   vhci_hcd_probe+0xf1/0x250
   platform_probe+0x69/0xe0
   really_probe+0x163/0x660
   __driver_probe_device+0x106/0x240
   device_driver_attach+0x7d/0x110
   bind_store+0x95/0xe0
   kernfs_fop_write_iter+0x1e0/0x280
   vfs_write+0x469/0x810
   ksys_write+0xd2/0x170
   do_syscall_64+0x115/0x6a0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f

  Second to last potentially related work creation:
   kasan_save_stack+0x33/0x60
   kasan_record_aux_stack+0x8c/0xa0
   __queue_work+0x661/0xa90
   queue_work_on+0x5f/0xb0
   usb_hcd_submit_urb+0x41c/0xf30
   usb_start_wait_urb+0xd8/0x2d0
   usb_control_msg+0x1c6/0x250
   hub_suspend+0x37d/0x4f0
   usb_suspend_both+0x170/0x4c0
   usb_runtime_suspend+0x30/0x90
   __rpm_callback+0x67/0x290
   rpm_callback+0xab/0xc0
   rpm_suspend+0x1c2/0x970
   __pm_runtime_suspend+0x3d/0x1d0
   usb_new_device+0x645/0x870
   register_root_hub+0x146/0x320
   usb_add_hcd+0x726/0xbd0
   vhci_hcd_probe+0xf1/0x250
   platform_probe+0x69/0xe0
   really_probe+0x163/0x660
   __driver_probe_device+0x106/0x240
   device_driver_attach+0x7d/0x110
   bind_store+0x95/0xe0
   kernfs_fop_write_iter+0x1e0/0x280
   vfs_write+0x469/0x810
   ksys_write+0xd2/0x170
   do_syscall_64+0x115/0x6a0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f

  The buggy address belongs to the object at ffff8880095f4000 which
  belongs to the cache kmalloc-8k of size 8192.
  The buggy address is located 1144 bytes inside of freed 8192-byte
  region [ffff8880095f4000, ffff8880095f6000).

A simplified ordering is:

  VHCI bind/test-remove path           sysfs reader
    vhci_hcd_probe()                     cat vhci_hcd.0/status
    usb_add_hcd() for SS HCD
    test remove runs
    vhci_hcd_remove()
    usb_remove_hcd()
    usb_put_hcd() frees SS HCD           status_show() walks SS state

Reproducer, run as root on a KASAN kernel with CONFIG_USBIP_VHCI_HCD
and CONFIG_DEBUG_TEST_DRIVER_REMOVE enabled:

  set -e
  modprobe vhci_hcd || true

  status=/sys/devices/platform/vhci_hcd.0/status
  bind=/sys/bus/platform/drivers/vhci_hcd/bind
  unbind=/sys/bus/platform/drivers/vhci_hcd/unbind
  dev=vhci_hcd.0

  if [ -e "$status" ]; then
          echo "$dev" > "$unbind" 2>/dev/null || true
  fi

  (
          deadline=$((SECONDS + 30))
          while [ ! -e "$status" ]; do
                  [ "$SECONDS" -lt "$deadline" ] || exit 1
                  sleep 0.1
          done

          for i in $(seq 1 50000); do
                  [ -e "$status" ] || break
                  cat "$status" >/dev/null 2>&1 || true
          done
  ) &

  reader=$!

  sleep 0.2
  echo "$dev" > "$bind"

  wait "$reader"

This looks like the vhci sysfs group needs to be published only after all
state reachable from the callbacks is live, and removed before any of that
state is removed or put.

Thanks,
Cen

                 reply	other threads:[~2026-06-23  3:16 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260623031609.138269-1-zzzccc427@gmail.com \
    --to=zzzccc427@gmail.com \
    --cc=baijiaju1990@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=i@zenithal.me \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=shuah@kernel.org \
    --cc=valentina.manea.m@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox