mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [BUG] KASAN: slab-use-after-free Read in usx2y_async_seq04_init
@ 2026-09-11 15:53 Farhad Alemi
  2026-09-12 12:34 ` Takashi Iwai
  0 siblings, 1 reply; 2+ messages in thread
From: Farhad Alemi @ 2026-09-11 15:53 UTC (permalink / raw)
  To: Jaroslav Kysela, Takashi Iwai; +Cc: linux-sound, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 10646 bytes --]

Hello,

We are reporting the following crash (reproducer attached):
Linux version 7.3.0-rc2 50d05c7c76c96b90462f24debacca971d2e86713
Build Config: UpstreamAppArmorKASAN (KASAN + UBSAN, panic_on_warn=1)

[   44.599577][ T9507] BUG: KASAN: slab-use-after-free in
usx2y_async_seq04_init+0x2b8/0x360
[   44.599666][ T9507] Read of size 4 at addr ffff8881060f6000 by task
repro/9507
[   44.599694][ T9507]
[   44.599736][ T9507] CPU: 1 UID: 0 PID: 9507 Comm: repro Not tainted
7.3.0-rc2-00099-g50d05c7c76c9 #1 PREEMPT(full)
[   44.599774][ T9507] Hardware name: QEMU Standard PC (Q35 + ICH9,
2009), BIOS 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
[   44.599807][ T9507] Call Trace:
[   44.599827][ T9507]  <TASK>
[   44.599877][ T9507]  dump_stack_lvl+0xe8/0x150
[   44.599917][ T9507]  print_address_description+0x55/0x1e0
[   44.599952][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.599982][ T9507]  print_report+0x58/0x70
[   44.600012][ T9507]  kasan_report+0x117/0x150
[   44.600055][ T9507]  ? __kmalloc_noprof+0x1af/0x720
[   44.600093][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.600130][ T9507]  usx2y_async_seq04_init+0x2b8/0x360
[   44.600168][ T9507]  snd_usx2y_hwdep_dsp_load+0x232/0x5e0
[   44.600205][ T9507]  ? __pfx_snd_usx2y_hwdep_dsp_load+0x10/0x10
[   44.600247][ T9507]  snd_hwdep_ioctl+0x489/0x590
[   44.600288][ T9507]  ? __pfx_snd_usx2y_hwdep_dsp_load+0x10/0x10
[   44.600322][ T9507]  ? __pfx_snd_hwdep_ioctl+0x10/0x10
[   44.600369][ T9507]  ? __fget_files+0x2a/0x420
[   44.600402][ T9507]  ? __fget_files+0x2a/0x420
[   44.600430][ T9507]  ? __fget_files+0x3a0/0x420
[   44.600460][ T9507]  ? __fget_files+0x2a/0x420
[   44.600491][ T9507]  ? bpf_lsm_file_ioctl+0x9/0x20
[   44.600525][ T9507]  ? __pfx_snd_hwdep_ioctl+0x10/0x10
[   44.600585][ T9507]  __se_sys_ioctl+0xfc/0x170
[   44.600625][ T9507]  do_syscall_64+0x155/0x510
[   44.600670][ T9507]  ? trace_irq_disable+0x3b/0x140
[   44.600709][ T9507]  ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   44.600741][ T9507]  ? clear_bhb_loop+0x30/0x80
[   44.600775][ T9507]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   44.600807][ T9507] RIP: 0033:0x41b46d
[   44.600860][ T9507] Code: 04 25 28 00 00 00 48 89 45 c8 31 c0 48 8d
45 10 c7 45 b0 10 00 00 00 48 89 45 b8 48 8d 45 d0 48 89 45 c0 b8 10
00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1a 48 8b 45 c8 64 48 2b 04 25
28 00 00 00
[   44.600895][ T9507] RSP: 002b:00007f916b837100 EFLAGS: 00000246
ORIG_RAX: 0000000000000010
[   44.600939][ T9507] RAX: ffffffffffffffda RBX: 00007f916b8376c0
RCX: 000000000041b46d
[   44.600963][ T9507] RDX: 00007f916b837170 RSI: 0000000040604803
RDI: 0000000000000004
[   44.600984][ T9507] RBP: 00007f916b837150 R08: 0000000000000000
R09: 00007f916b837174
[   44.601006][ T9507] R10: 0000000000000008 R11: 0000000000000246
R12: 00007f916b8376c0
[   44.601026][ T9507] R13: 00007fff5766a470 R14: 00007f916b837ce4
R15: 00007fff5766a567
[   44.601060][ T9507]  </TASK>
[   44.601072][ T9507]
[   44.601086][ T9507] Allocated by task 988:
[   44.601102][ T9507]  kasan_save_track+0x3e/0x80
[   44.601139][ T9507]  __kasan_kmalloc+0x93/0xb0
[   44.601176][ T9507]  __kmalloc_cache_noprof+0x325/0x610
[   44.601211][ T9507]  usb_alloc_dev+0x5d/0xf00
[   44.601265][ T9507]  hub_event+0x21ce/0x4f30
[   44.601298][ T9507]  process_scheduled_works+0xc99/0x1900
[   44.601343][ T9507]  worker_thread+0xa53/0xfc0
[   44.601370][ T9507]  kthread+0x38b/0x480
[   44.601402][ T9507]  ret_from_fork+0x514/0xb70
[   44.601434][ T9507]  ret_from_fork_asm+0x1a/0x30
[   44.601467][ T9507]
[   44.601475][ T9507] Freed by task 988:
[   44.601489][ T9507]  kasan_save_track+0x3e/0x80
[   44.601523][ T9507]  kasan_save_free_info+0x46/0x50
[   44.601551][ T9507]  __kasan_slab_free+0x5c/0x80
[   44.601587][ T9507]  kfree+0x1c5/0x650
[   44.601614][ T9507]  device_release+0xc4/0x1f0
[   44.601649][ T9507]  kobject_put+0x228/0x560
[   44.601678][ T9507]  hub_event+0x1cc9/0x4f30
[   44.601711][ T9507]  process_scheduled_works+0xc99/0x1900
[   44.601754][ T9507]  worker_thread+0xa53/0xfc0
[   44.601780][ T9507]  kthread+0x38b/0x480
[   44.601812][ T9507]  ret_from_fork+0x514/0xb70
[   44.601844][ T9507]  ret_from_fork_asm+0x1a/0x30
[   44.601896][ T9507]
[   44.601903][ T9507] The buggy address belongs to the object at
ffff8881060f6000
[   44.601903][ T9507]  which belongs to the cache kmalloc-2k of size 2048
[   44.601939][ T9507] The buggy address is located 0 bytes inside of
[   44.601939][ T9507]  freed 2048-byte region [ffff8881060f6000,
ffff8881060f6800)
[   44.601972][ T9507]
[   44.601980][ T9507] The buggy address belongs to the physical page:
[   44.602011][ T9507] page: refcount:0 mapcount:0
mapping:0000000000000000 index:0x0 pfn:0x1060f0
[   44.602041][ T9507] head: order:3 mapcount:0 entire_mapcount:0
nr_pages_mapped:0 pincount:0
[   44.602067][ T9507] flags:
0x57ff00000000040(head|node=1|zone=2|lastcpupid=0x7ff)
[   44.602110][ T9507] page_type: f5(slab)
[   44.602148][ T9507] raw: 057ff00000000040 ffff88801b042000
dead000000000100 dead000000000122
[   44.602174][ T9507] raw: 0000000000000000 0000000000080008
00000000f5000000 0000000000000000
[   44.602202][ T9507] head: 057ff00000000040 ffff88801b042000
dead000000000100 dead000000000122
[   44.602228][ T9507] head: 0000000000000000 0000000000080008
00000000f5000000 0000000000000000
[   44.602255][ T9507] head: 057ff00000000003 fffffffffffffe01
00000000ffffffff 00000000ffffffff
[   44.602280][ T9507] head: ffffffffffffffff 0000000000000000
00000000ffffffff 0000000000000008
[   44.602296][ T9507] page dumped because: kasan: bad access detected
[   44.602318][ T9507] page_owner tracks the page as allocated
[   44.602330][ T9507] page last allocated via order 3, migratetype
Unmovable, gfp_mask
0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC),
pid 1, tgid 1 (swapper/0), ts 1751673867
[   44.602381][ T9507]  post_alloc_hook+0x1f9/0x250
[   44.602412][ T9507]  get_page_from_freelist+0x235a/0x23e0
[   44.602449][ T9507]  __alloc_frozen_pages_noprof+0x217/0x5a0
[   44.602486][ T9507]  allocate_slab+0x7d/0x610
[   44.602511][ T9507]  refill_objects+0x2d6/0x350
[   44.602536][ T9507]  __pcs_replace_empty_main+0x2c9/0x6c0
[   44.602578][ T9507]  __kmalloc_cache_noprof+0x3a5/0x610
[   44.602612][ T9507]  container_device_attach+0x8e/0x220
[   44.602645][ T9507]  acpi_bus_attach+0x6fb/0xb90
[   44.602676][ T9507]  device_for_each_child+0x10b/0x1a0
[   44.602705][ T9507]  acpi_dev_for_each_child+0x9b/0xe0
[   44.602747][ T9507]  acpi_bus_attach+0x900/0xb90
[   44.602777][ T9507]  device_for_each_child+0x10b/0x1a0
[   44.602806][ T9507]  acpi_dev_for_each_child+0x9b/0xe0
[   44.602858][ T9507]  acpi_bus_attach+0x900/0xb90
[   44.602889][ T9507]  device_for_each_child+0x10b/0x1a0
[   44.602919][ T9507] page_owner free stack trace missing
[   44.602930][ T9507]
[   44.602938][ T9507] Memory state around the buggy address:
[   44.602954][ T9507]  ffff8881060f5f00: fc fc fc fc fc fc fc fc fc
fc fc fc fc fc fc fc
[   44.602974][ T9507]  ffff8881060f5f80: fc fc fc fc fc fc fc fc fc
fc fc fc fc fc fc fc
[   44.602994][ T9507] >ffff8881060f6000: fa fb fb fb fb fb fb fb fb
fb fb fb fb fb fb fb
[   44.603010][ T9507]                    ^
[   44.603025][ T9507]  ffff8881060f6080: fb fb fb fb fb fb fb fb fb
fb fb fb fb fb fb fb
[   44.603045][ T9507]  ffff8881060f6100: fb fb fb fb fb fb fb fb fb
fb fb fb fb fb fb fb
[   44.603060][ T9507]
==================================================================
[   44.603093][ T9507] Kernel panic - not syncing: KASAN: panic_on_warn set ...
[   44.674986][ T9507] CPU: 1 UID: 0 PID: 9507 Comm: repro Not tainted
7.3.0-rc2-00099-g50d05c7c76c9 #1 PREEMPT(full)
[   44.675924][ T9507] Hardware name: QEMU Standard PC (Q35 + ICH9,
2009), BIOS 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
[   44.676874][ T9507] Call Trace:
[   44.677180][ T9507]  <TASK>
[   44.677502][ T9507]  vpanic+0x56d/0xa60
[   44.677905][ T9507]  ? __pfx_vpanic+0x10/0x10
[   44.678355][ T9507]  panic+0xc5/0xd0
[   44.678734][ T9507]  ? __pfx_panic+0x10/0x10
[   44.679179][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.679708][ T9507]  ? rcu_is_watching+0x16/0xb0
[   44.680182][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.680682][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.681188][ T9507]  check_panic_on_warn+0x89/0xb0
[   44.681642][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.682159][ T9507]  end_report+0x73/0x170
[   44.682551][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.683122][ T9507]  kasan_report+0x128/0x150
[   44.683540][ T9507]  ? __kmalloc_noprof+0x1af/0x720
[   44.684003][ T9507]  ? usx2y_async_seq04_init+0x2b8/0x360
[   44.684505][ T9507]  usx2y_async_seq04_init+0x2b8/0x360
[   44.684997][ T9507]  snd_usx2y_hwdep_dsp_load+0x232/0x5e0
[   44.685497][ T9507]  ? __pfx_snd_usx2y_hwdep_dsp_load+0x10/0x10
[   44.686053][ T9507]  snd_hwdep_ioctl+0x489/0x590
[   44.686491][ T9507]  ? __pfx_snd_usx2y_hwdep_dsp_load+0x10/0x10
[   44.687041][ T9507]  ? __pfx_snd_hwdep_ioctl+0x10/0x10
[   44.687523][ T9507]  ? __fget_files+0x2a/0x420
[   44.687948][ T9507]  ? __fget_files+0x2a/0x420
[   44.688368][ T9507]  ? __fget_files+0x3a0/0x420
[   44.688797][ T9507]  ? __fget_files+0x2a/0x420
[   44.689223][ T9507]  ? bpf_lsm_file_ioctl+0x9/0x20
[   44.689675][ T9507]  ? __pfx_snd_hwdep_ioctl+0x10/0x10
[   44.690158][ T9507]  __se_sys_ioctl+0xfc/0x170
[   44.690582][ T9507]  do_syscall_64+0x155/0x510
[   44.691011][ T9507]  ? trace_irq_disable+0x3b/0x140
[   44.691470][ T9507]  ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   44.692021][ T9507]  ? clear_bhb_loop+0x30/0x80
[   44.692465][ T9507]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[   44.693056][ T9507] RIP: 0033:0x41b46d
[   44.693415][ T9507] Code: 04 25 28 00 00 00 48 89 45 c8 31 c0 48 8d
45 10 c7 45 b0 10 00 00 00 48 89 45 b8 48 8d 45 d0 48 89 45 c0 b8 10
00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1a 48 8b 45 c8 64 48 2b 04 25
28 00 00 00
[   44.695144][ T9507] RSP: 002b:00007f916b837100 EFLAGS: 00000246
ORIG_RAX: 0000000000000010
[   44.695911][ T9507] RAX: ffffffffffffffda RBX: 00007f916b8376c0
RCX: 000000000041b46d
[   44.696658][ T9507] RDX: 00007f916b837170 RSI: 0000000040604803
RDI: 0000000000000004
[   44.697402][ T9507] RBP: 00007f916b837150 R08: 0000000000000000
R09: 00007f916b837174
[   44.698141][ T9507] R10: 0000000000000008 R11: 0000000000000246
R12: 00007f916b8376c0
[   44.698886][ T9507] R13: 00007fff5766a470 R14: 00007f916b837ce4
R15: 00007fff5766a567
[   44.699613][ T9507]  </TASK>
[   44.700387][ T9507] Kernel Offset: disabled
[   44.700934][ T9507] Rebooting in 86400 seconds..

Regards,

[-- Attachment #2: reproducer.c --]
[-- Type: application/octet-stream, Size: 7993 bytes --]

/*
 * 248-kasan-slab-use-after-free-read-in-usx2y-async-seq04-init
 */
#define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <linux/usb/ch9.h>
#include <linux/usb/raw_gadget.h>

#define EP0_MAX_PACKET 4096
#define LE16(v) ((v) & 0xff), (((v) >> 8) & 0xff)

#define TASCAM_VENDOR_ID  0x1604
#define TASCAM_US428_ID   0x8001

#define MAX_ALSA_CARDS 8

struct snd_hwdep_dsp_image_abi {
	unsigned int index;
	unsigned char name[64];
	unsigned char *image;
	size_t length;
	unsigned long driver_data;
};
#define SNDRV_HWDEP_IOCTL_DSP_LOAD 0x40604803u

#define CONTROL_REQUEST_OTHER             0
#define CONTROL_REQUEST_SET_CONFIGURATION 1
#define CONTROL_REQUEST_SET_INTERFACE_ALT1 2

static const struct usb_device_descriptor device_descriptor = {
	.bLength = 18,
	.bDescriptorType = USB_DT_DEVICE,
	.bcdUSB = 0x0200,
	.bMaxPacketSize0 = 64,
	.idVendor = TASCAM_VENDOR_ID,
	.idProduct = TASCAM_US428_ID,
	.bcdDevice = 0x0100,
	.bNumConfigurations = 1,
};

static const unsigned char config_descriptor[] = {
	9, USB_DT_CONFIG, LE16(9 + 9 + 9 + 7), 1, 1, 0, 0xa0, 0xfa,
	9, USB_DT_INTERFACE, 0, 0, 0, 0xff, 0xff, 0xff, 0,
	9, USB_DT_INTERFACE, 0, 1, 1, 0xff, 0xff, 0xff, 0,
	7, USB_DT_ENDPOINT, 0x02, USB_ENDPOINT_XFER_BULK, LE16(512), 0,
};

static int raw_gadget_fd = -1;
static int bulk_out_ep2_handle = -1;
static int hwdep_fd = -1;

static int find_dummy_udc(char *driver_name, size_t driver_len,
			  char *device_name, size_t device_len)
{
	DIR *udc_dir = opendir("/sys/class/udc");
	struct dirent *udc_entry;

	if (!udc_dir)
		return -1;
	while ((udc_entry = readdir(udc_dir))) {
		char *instance_suffix;

		if (udc_entry->d_name[0] == '.')
			continue;
		snprintf(device_name, device_len, "%s", udc_entry->d_name);
		snprintf(driver_name, driver_len, "%s", udc_entry->d_name);

		instance_suffix = strrchr(driver_name, '.');
		if (instance_suffix)
			*instance_suffix = 0;
		closedir(udc_dir);
		return 0;
	}
	closedir(udc_dir);
	return -1;
}

static int ep0_send_data(const void *data, unsigned int length)
{
	unsigned char buffer[sizeof(struct usb_raw_ep_io) + EP0_MAX_PACKET];
	struct usb_raw_ep_io *ep0_io = (void *)buffer;

	ep0_io->ep = 0;
	ep0_io->flags = 0;
	ep0_io->length = length;
	memcpy(ep0_io->data, data, length);
	return ioctl(raw_gadget_fd, USB_RAW_IOCTL_EP0_WRITE, ep0_io);
}

static int ep0_complete_status_stage(unsigned short wLength)
{
	unsigned char buffer[sizeof(struct usb_raw_ep_io) + EP0_MAX_PACKET];
	struct usb_raw_ep_io *ep0_io = (void *)buffer;

	ep0_io->ep = 0;
	ep0_io->flags = 0;
	ep0_io->length = wLength > EP0_MAX_PACKET ? EP0_MAX_PACKET : wLength;
	return ioctl(raw_gadget_fd, USB_RAW_IOCTL_EP0_READ, ep0_io);
}

static void enable_bulk_out_ep2(void)
{
	struct usb_endpoint_descriptor endpoint_descriptor = {
		.bLength = USB_DT_ENDPOINT_SIZE,
		.bDescriptorType = USB_DT_ENDPOINT,
		.bEndpointAddress = 0x02,
		.bmAttributes = USB_ENDPOINT_XFER_BULK,
		.wMaxPacketSize = 512,
	};

	if (bulk_out_ep2_handle < 0)
		bulk_out_ep2_handle = ioctl(raw_gadget_fd,
					    USB_RAW_IOCTL_EP_ENABLE,
					    &endpoint_descriptor);
}

static void drain_bulk_out_ep2(void)
{
	unsigned char buffer[sizeof(struct usb_raw_ep_io) + 1024];
	struct usb_raw_ep_io *ep_io = (void *)buffer;

	if (bulk_out_ep2_handle < 0)
		return;
	ep_io->ep = bulk_out_ep2_handle;
	ep_io->flags = 0;
	ep_io->length = 512;
	ioctl(raw_gadget_fd, USB_RAW_IOCTL_EP_READ, ep_io);
}

static int handle_ep0_control_request(const struct usb_ctrlrequest *control)
{
	unsigned char reply[EP0_MAX_PACKET];
	int reply_length = -1;
	int outcome = CONTROL_REQUEST_OTHER;

	if ((control->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
		switch (control->bRequest) {
		case USB_REQ_GET_DESCRIPTOR:
			if ((control->wValue >> 8) == USB_DT_DEVICE) {
				reply_length = sizeof(device_descriptor);
				memcpy(reply, &device_descriptor, reply_length);
			} else if ((control->wValue >> 8) == USB_DT_CONFIG) {
				reply_length = sizeof(config_descriptor);
				memcpy(reply, config_descriptor, reply_length);
			}
			break;
		case USB_REQ_SET_CONFIGURATION:
			ioctl(raw_gadget_fd, USB_RAW_IOCTL_CONFIGURE, 0);
			enable_bulk_out_ep2();
			reply_length = 0;
			outcome = CONTROL_REQUEST_SET_CONFIGURATION;
			break;
		case USB_REQ_SET_INTERFACE:
			reply_length = 0;
			if (control->wValue == 1)
				outcome = CONTROL_REQUEST_SET_INTERFACE_ALT1;
			break;
		}
	}

	if (reply_length < 0) {
		ioctl(raw_gadget_fd, USB_RAW_IOCTL_EP0_STALL, 0);
		return CONTROL_REQUEST_OTHER;
	}
	if ((control->bRequestType & USB_DIR_IN) && control->wLength) {
		if (reply_length > (int)control->wLength)
			reply_length = control->wLength;
		ep0_send_data(reply, (unsigned int)reply_length);
	} else {
		ep0_complete_status_stage(control->wLength);
	}
	return outcome;
}

static void snapshot_existing_hwdep_nodes(int *hwdep_present_before)
{
	for (int card = 0; card < MAX_ALSA_CARDS; card++) {
		char path[64];
		int fd;

		snprintf(path, sizeof(path), "/dev/snd/hwC%dD0", card);
		fd = open(path, O_RDONLY);
		hwdep_present_before[card] = (fd >= 0);
		if (fd >= 0)
			close(fd);
	}
}

static int open_hwdep_node_created_by_probe(const int *hwdep_present_before)
{
	for (int attempt = 0; attempt < 80; attempt++) {
		for (int card = 0; card < MAX_ALSA_CARDS; card++) {
			char path[64];
			int fd;

			if (hwdep_present_before[card])
				continue;
			snprintf(path, sizeof(path), "/dev/snd/hwC%dD0", card);
			fd = open(path, O_RDWR);
			if (fd >= 0)
				return fd;
		}
		usleep(50000);
	}
	return -1;
}

static void *dsp_load_thread(void *unused)
{
	struct snd_hwdep_dsp_image_abi dsp_image;
	unsigned char firmware_bytes[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };

	memset(&dsp_image, 0, sizeof(dsp_image));
	dsp_image.index = 1;
	dsp_image.image = firmware_bytes;
	dsp_image.length = sizeof(firmware_bytes);
	ioctl(hwdep_fd, SNDRV_HWDEP_IOCTL_DSP_LOAD, &dsp_image);
	return NULL;
}

int main(void)
{
	char gadget_driver_name[128], udc_device_name[128];
	struct usb_raw_init raw_gadget_init;
	unsigned char event_buffer[sizeof(struct usb_raw_event) + EP0_MAX_PACKET];
	struct usb_raw_event *event = (void *)event_buffer;
	int hwdep_present_before[MAX_ALSA_CARDS];
	pthread_t loader_thread;
	int loader_started = 0;

	system("modprobe dummy_hcd 2>/dev/null");
	system("modprobe raw_gadget 2>/dev/null");
	system("modprobe snd-usb-usx2y 2>/dev/null");

	if (find_dummy_udc(gadget_driver_name, sizeof(gadget_driver_name),
			   udc_device_name, sizeof(udc_device_name)) < 0)
		return 1;

	snapshot_existing_hwdep_nodes(hwdep_present_before);

	raw_gadget_fd = open("/dev/raw-gadget", O_RDWR);
	if (raw_gadget_fd < 0)
		return 1;
	memset(&raw_gadget_init, 0, sizeof(raw_gadget_init));
	strncpy((char *)raw_gadget_init.driver_name, gadget_driver_name,
		sizeof(raw_gadget_init.driver_name) - 1);
	strncpy((char *)raw_gadget_init.device_name, udc_device_name,
		sizeof(raw_gadget_init.device_name) - 1);
	raw_gadget_init.speed = USB_SPEED_HIGH;
	if (ioctl(raw_gadget_fd, USB_RAW_IOCTL_INIT, &raw_gadget_init) < 0)
		return 1;
	if (ioctl(raw_gadget_fd, USB_RAW_IOCTL_RUN, 0) < 0)
		return 1;

	for (;;) {
		int outcome;

		event->type = 0;
		event->length = EP0_MAX_PACKET;
		if (ioctl(raw_gadget_fd, USB_RAW_IOCTL_EVENT_FETCH, event) < 0)
			return 1;
		if (event->type != USB_RAW_EVENT_CONTROL)
			continue;

		outcome = handle_ep0_control_request(
				(struct usb_ctrlrequest *)event->data);

		if (outcome == CONTROL_REQUEST_SET_CONFIGURATION && !loader_started) {
			hwdep_fd = open_hwdep_node_created_by_probe(hwdep_present_before);
			if (hwdep_fd < 0)
				return 1;
			pthread_create(&loader_thread, NULL, dsp_load_thread, NULL);
			loader_started = 1;
		}
		if (outcome == CONTROL_REQUEST_SET_INTERFACE_ALT1) {
			drain_bulk_out_ep2();

			usleep(120000);
			break;
		}
	}

	close(raw_gadget_fd);
	if (loader_started)
		pthread_join(loader_thread, NULL);
	return 0;
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [BUG] KASAN: slab-use-after-free Read in usx2y_async_seq04_init
  2026-09-11 15:53 [BUG] KASAN: slab-use-after-free Read in usx2y_async_seq04_init Farhad Alemi
@ 2026-09-12 12:34 ` Takashi Iwai
  0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2026-09-12 12:34 UTC (permalink / raw)
  To: Farhad Alemi; +Cc: Jaroslav Kysela, Takashi Iwai, linux-sound, linux-kernel

On Fri, 11 Sep 2026 17:53:55 +0200,
Farhad Alemi wrote:
> 
> Hello,
> 
> We are reporting the following crash (reproducer attached):
> Linux version 7.3.0-rc2 50d05c7c76c96b90462f24debacca971d2e86713
> Build Config: UpstreamAppArmorKASAN (KASAN + UBSAN, panic_on_warn=1)
> 
> [   44.599577][ T9507] BUG: KASAN: slab-use-after-free in
> usx2y_async_seq04_init+0x2b8/0x360
(snip)

Both this one and your another report ("[BUG] KASAN:
slab-use-after-free Read in __snd_ctl_add_replace") are basically the
same issue -- UAFs after the card release of USB drivers that are done
asynchronously from the disconnect callback.

Below is the fix patch for both.


thanks,

Takashi

-- 8< --
From: Takashi Iwai <tiwai@suse.de>
Subject: [PATCH] ALSA: core: Fix potential UAF after asynchronous card release

Usually a sound driver releases the resources assigned to the card via
snd_card_free(), and it synchronizes with the whole release procedure.
However, when the card is released asynchronously via
snd_card_free_when_closed() like USB-audio driver, the situation is
slightly different; although the snd_card_disconnect() call at the
disconnection guarantees that any newer accesses will be gated, the
in-flight tasks might be still accessing to the underlying card->dev
device even after the disconnection, which would cause a
use-after-free in the end, as reported by fuzzers.

For addressing the bug above, this patch takes the refcount of
card->dev at initialization of the card object, and releases at its
destructor.   This assures the availability of the card->dev in its
whole lifecycle.

Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>
Closes: https://lore.kernel.org/CA+0ovChexj4TrZL_2iG_P0WBEbZc5+73GfB3DkciQi=R8pZOnA@mail.gmail.com
Closes: https://lore.kernel.org/CA+0ovCgQUQNN=Z1tJTouiCsDaXR5M-3-SQEGk-cpPXQkM5Xh+w@mail.gmail.com
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/core/init.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/core/init.c b/sound/core/init.c
index 2f7f83a7611b..bffa94b7b956 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -310,7 +310,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
 			kfree(card); /* manually free here, as no destructor called */
 		return err;
 	}
-	card->dev = parent;
+	card->dev = get_device(parent);
 	card->number = idx;
 	WARN_ON(IS_MODULE(CONFIG_SND) && !module);
 	card->module = module;
@@ -605,6 +605,7 @@ static int snd_card_do_free(struct snd_card *card)
 	}
 	if (card->release_completion)
 		complete(card->release_completion);
+	put_device(card->dev);
 	if (!managed)
 		kfree(card);
 	return 0;
-- 
2.55.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-12 12:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-11 15:53 [BUG] KASAN: slab-use-after-free Read in usx2y_async_seq04_init Farhad Alemi
2026-09-12 12:34 ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®