mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: 徐晗翔 <xuhx@hust.edu.cn>
To: perex@perex.cz, tiwai@suse.com
Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: ALSA: usb-audio: us144mkii: PCM close frees runtime while playback/feedback URB completion and capture work still use it (UAF)
Date: Fri, 13 Nov 2026 20:28:42 +0800 (GMT+08:00)	[thread overview]
Message-ID: <12a3a26a.26361.1a1d4e1ad57.Coremail.xuhx@hust.edu.cn> (raw)
In-Reply-To: <2026102727-data-sequel-ce41@gregkh>

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

tascam_playback_close() and tascam_capture_close() only clear the
substream pointer; they do not stop URBs or cancel work.  The ALSA
release path then calls snd_pcm_detach_substream(), which sets
substream->runtime to NULL and frees the snd_pcm_runtime.  A
playback/feedback URB completion, or the capture work, can have loaded
the substream/runtime pointer before close; after detach it dereferences
runtime->rate, runtime->buffer_size, runtime->dma_area or
runtime->status, and may resubmit the next URB.  This is a
use-after-free / oops on an ordinary PCM close while the device remains
connected.  It is not the disconnect path.  Capture close is also
affected because feedback_urb_complete() uses the capture runtime.

The detailed description:

* Test environment / affected version

  Linux 7.3.0 source tree (VERSION=7, PATCHLEVEL=3, SUBLEVEL=0),
  sound/usb/usx2y/us144mkii.c, us144mkii_playback.c,
  us144mkii_capture.c and us144mkii_pcm.c.  The driver binds the
  TASCAM US-144MKII (0644:8020) and US-144 (0644:800f).  The relevant
  configuration is CONFIG_SND_USB_US144MKII=m.

  This report is based on source inspection, plus a synthetic ALSA PCM
  model used to validate the close/detach lifetime pattern (see
  "Reproducer (attached POC)" below).  I have not run the real driver on
  TASCAM hardware or under KASAN; no real-hardware result is claimed.

* Mechanism

  1. The close callbacks do not stop I/O:

     static int tascam_playback_close(struct snd_pcm_substream *substream)
     {
             struct tascam_card *tascam = snd_pcm_substream_chip(substream);

             tascam->playback_substream = NULL;
             return 0;
     }

     (us144mkii_playback.c:35-42; tascam_capture_close() is the same at
     us144mkii_capture.c:35-42).  No usb_kill_urb(), no
     cancel_work_sync().

  2. tascam_pcm_trigger() on STOP only clears the active flags and
     schedules stop_work asynchronously:

             atomic_set(&tascam->playback_active, 0);
             atomic_set(&tascam->capture_active, 0);
             ...
             schedule_work(&tascam->stop_work);

     (us144mkii_pcm.c:280-287 and 352-353).  tascam_pcm_hw_free() is a
     no-op (us144mkii_pcm.c:257-260), so ALSA's do_hw_free() cannot stop
     anything either.

  3. ALSA then frees the runtime:

             snd_pcm_drop(substream);                  /* trigger STOP */
             ...
             substream->ops->close(substream);         /* only NULLs ptr */
             ...
             snd_pcm_detach_substream(substream);      /* frees runtime */

     (sound/core/pcm_native.c:2785-2805; snd_pcm_detach_substream() at
     sound/core/pcm.c:978-1005, substream->runtime = NULL at 997 and
     kfree(runtime) at 1001).

  4. Three consumers can already hold the old runtime pointer:

     - playback_urb_complete() reads tascam->playback_substream and
       substream->runtime at us144mkii_playback.c:176-182, then uses
       runtime->rate / runtime->buffer_size under tascam->lock and
       runtime->dma_area after unlocking (184-234), before resubmitting
       at 237-247.

     - feedback_urb_complete() reads the playback and capture
       substreams at us144mkii_playback.c:282-288.  It uses
       capture_rt->period_size at 413-417 and calls
       snd_pcm_period_elapsed(capture_ss) at 430 after unlocking.
       Therefore capture close must also stop the feedback URB; it
       currently stops neither capture nor feedback URBs.

     - tascam_capture_work_handler() reads
       tascam->capture_substream and substream->runtime at
       us144mkii_capture.c:157-169 and writes runtime->dma_area at 230
       under tascam->lock.  It is queued by capture_urb_complete() at
       line 301.

  5. The asynchronous stop_work is not a close-time barrier.
     usb_kill_anchored_urbs() in tascam_stop_work_handler() does wait
     for a completion that is already inside the HCD giveback path
     (__usb_hcd_giveback_urb() suspends the anchor wakeups before
     usb_unanchor_urb(), and resumes them only after urb->complete()),
     but stop_work itself is scheduled asynchronously by trigger(STOP).
     close does not wait for stop_work, so detach can free the runtime
     before stop_work runs.  A per-URB usb_kill_urb() in close() is the
     explicit synchronous barrier; it waits for urb->use_count == 0
     (drivers/usb/core/urb.c:703-720).

  6. A completion that has already passed the active/pointer check can
     resubmit a URB after close's kill unless the final check and
     usb_submit_urb() are serialized with close.  The close path must
     clear the active flag and substream pointer under tascam->lock,
     kill the URBs, cancel the work, and make the completion's final
     submit path take the same lock.

  7. There is a second direction: feedback completion consumes the
     capture runtime, but tascam_capture_close() stops neither capture
     URBs nor feedback URBs.  Closing capture while playback (and
     therefore feedback) remains open can free capture_runtime while
     feedback completion still uses capture_rt.

  8. close() must also be serialized with tascam_disconnect():
     tascam_disconnect() calls tascam_free_urbs() before
     snd_card_free() waits for open PCM files to close
     (us144mkii.c:580-611; free at 38-110).  Without a
     disconnect_lock/disconnected flag, a close that runs after the
     slots were freed can call usb_kill_urb(NULL), or race the free.



* Reproducer

  Attached files:
    tascam_poc.c  - synthetic ALSA PCM kernel module (C1 mode pcm1)
    pcmtest.c     - userland exerciser
    Makefile      - builds tascam_poc.ko against the running kernel

  This POC does not drive the TASCAM device.  It creates a synthetic ALSA
  PCM card whose .close() only drops the substream pointer, starts an
  asynchronous work item that caches the runtime, and lets ALSA detach and
  free the runtime before the work runs.  It therefore reproduces the
  lifetime ordering in point 3/4 above, not the real USB URB completion.
  A KASAN kernel is required to observe the UAF.

  Build and run:
    make
    gcc -static -O2 -o pcmtest pcmtest.c
    sudo modprobe snd-pcm
    sudo insmod ./tascam_poc.ko mode=pcm1
    sudo ./pcmtest 1
    dmesg | tail -50
    sudo rmmod tascam_poc

  Expected result with KASAN:
    BUG: KASAN: slab-use-after-free in race_pcm_work+0xce/0x140
    Allocated by task ... (snd_pcm_open)
    Freed by task ... (snd_pcm_release_substream/snd_pcm_detach_substream)

  Negative control (close cancels the work):
    sudo insmod ./tascam_poc.ko mode=pcm1 safe=1
    sudo ./pcmtest 1
  Expected: no KASAN report.

  The module creates a capture PCM at card index 0; if that index is
  occupied, check /proc/asound/cards and adjust DEV in pcmtest.c.

  For a real-hardware KASAN run, the proposed procedure is:

    arecord -D hw:CARD=US144MKII,DEV=0 -f S32_LE -r 48000 -c 4 /dev/null &
    aplay    -D hw:CARD=US144MKII,DEV=0 -f S32_LE -r 48000 -c 4 /dev/zero
    # start playback, then close it while feedback is active;
    # repeat open/start/close in a loop and watch dmesg for KASAN

  For the capture-close direction, keep the playback process running
  and repeatedly open/start/close the capture stream.  The expected
  KASAN top frames are playback_urb_complete(), feedback_urb_complete()
  or tascam_capture_work_handler().


* Suggested direction 

  In .close(), under tascam->lock, clear the active flag and substream
  pointer, then call usb_kill_urb() for every feedback/playback URB
  (capture close: feedback/capture), and finally cancel_work_sync() for
  stop_pcm_work, stop_work and capture_work as appropriate, before
  returning to snd_pcm_detach_substream().

  Use a disconnect_lock plus a disconnected flag to serialize this
  cleanup with tascam_disconnect()'s tascam_free_urbs(); release the
  lock before snd_card_free().  The completion's final
  active/pointer check and usb_anchor_urb()/usb_submit_urb() should run
  under the same tascam->lock, so a completion that raced with close
  cannot submit a new URB after the kill.

  I am happy to test a proposed fix.


Please keep me in Cc; I am not subscribed to the lists.


Regards,
Hanxiang Xu
xuhx@hust.edu.cn

[-- Attachment #2: tascam_poc.c --]
[-- Type: text/plain, Size: 6616 bytes --]

// SPDX-License-Identifier: GPL-2.0
/*
 * tascam_poc.c - synthetic ALSA PCM lifetime reproducer for the TASCAM
 * US-144MKII manual-review cases C1 and C2.
 *
 * This module deliberately reproduces the *lifetime patterns* of the driver,
 * not the USB device itself:
 *   pcm1 : ALSA PCM .close() drops the runtime while an asynchronous
 *          "completion" still holds a runtime pointer (C1).
 *   pcm2 : a queued work item calls snd_pcm_stop() after .close()/detach
 *          (C2).
 *
 * The ALSA card is a synthetic platform device; no TASCAM hardware or USB
 * traffic is involved.  Build and run instructions are in README.txt.
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>

#define DRV "sndusb_race"
#define COOKIE 0x5a5a1234deadbeefULL

static char *mode = "pcm1";
module_param(mode, charp, 0444);
static bool safe;
module_param(safe, bool, 0444);
MODULE_PARM_DESC(mode, "pcm1 or pcm2");
MODULE_PARM_DESC(safe, "take the safe cleanup path (negative control)");

/* ------------------------------------------------------------------ */
/* V1/V2 synthetic ALSA PCM                                            */
/* ------------------------------------------------------------------ */
struct race_pcm {
	struct snd_pcm_substream *substream;
	struct snd_pcm_runtime *runtime;
	struct work_struct work;
	atomic_t active;
	bool c2;
	u64 cookie;
};

static struct snd_card *race_card;
static struct platform_device *race_pdev;
static struct snd_pcm *race_pcm_dev;

static void race_pcm_work(struct work_struct *work)
{
	struct race_pcm *m = container_of(work, struct race_pcm, work);
	struct snd_pcm_runtime *rt = m->runtime;
	struct snd_pcm_substream *ss = m->substream;

	pr_info(DRV ": work start mode=%s rt=%px ss=%px cookie=%#llx\n",
		m->c2 ? "c2" : "c1", rt, ss, m->cookie);
	if (!m->c2 && !rt)
		return;
	if (m->c2 && !ss)
		return;

	/* Give the closing thread time to run .close() and detach/free. */
	msleep(120);

	if (!m->c2) {
		/*
		 * C1: the completion cached runtime before close; after
		 * snd_pcm_detach_substream() this is freed memory.
		 */
		pr_info(DRV ": c1 use rt=%px dma_area=%px\n", rt,
			READ_ONCE(rt->dma_area));
		barrier();
		(void)READ_ONCE(rt->dma_area);
	} else {
		/*
		 * C2: the work cached the substream, but detach made
		 * ss->runtime NULL; snd_pcm_stop() dereferences it.
		 */
		pr_info(DRV ": c2 call snd_pcm_stop ss=%px runtime=%px\n",
			ss, READ_ONCE(ss->runtime));
		snd_pcm_stop(ss, SNDRV_PCM_STATE_XRUN);
	}
	pr_info(DRV ": work end\n");
}

static int race_pcm_open(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct race_pcm *m;

	m = kzalloc(sizeof(*m), GFP_KERNEL);
	if (!m)
		return -ENOMEM;
	m->substream = substream;
	m->runtime = runtime;
	m->cookie = COOKIE;
	m->c2 = !strcmp(mode, "pcm2");
	INIT_WORK(&m->work, race_pcm_work);
	atomic_set(&m->active, 0);
	runtime->private_data = m;
	runtime->hw.info = SNDRV_PCM_INFO_MMAP |
			   SNDRV_PCM_INFO_INTERLEAVED |
			   SNDRV_PCM_INFO_MMAP_VALID;
	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
	runtime->hw.rates = SNDRV_PCM_RATE_44100;
	runtime->hw.rate_min = 44100;
	runtime->hw.rate_max = 44100;
	runtime->hw.channels_min = 2;
	runtime->hw.channels_max = 2;
	runtime->hw.buffer_bytes_max = 64 * 1024;
	runtime->hw.period_bytes_min = 1024;
	runtime->hw.period_bytes_max = 4096;
	runtime->hw.periods_min = 2;
	runtime->hw.periods_max = 8;
	pr_info(DRV ": open sub=%px rt=%px mode=%s\n", substream, runtime, mode);
	return 0;
}

static int race_pcm_close(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct race_pcm *m = runtime ? runtime->private_data : NULL;

	pr_info(DRV ": close sub=%px rt=%px m=%px safe=%d\n",
		substream, runtime, m, safe);
	if (m && safe)
		cancel_work_sync(&m->work);
	if (m) {
		m->substream = NULL;
		m->runtime = NULL;
	}
	return 0;
}

static int race_pcm_hw_params(struct snd_pcm_substream *substream,
			      struct snd_pcm_hw_params *params)
{
	return 0;
}

static int race_pcm_prepare(struct snd_pcm_substream *substream)
{
	return 0;
}

static int race_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct race_pcm *m = runtime ? runtime->private_data : NULL;

	if (!m)
		return 0;
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
		atomic_set(&m->active, 1);
		pr_info(DRV ": trigger start, queue work\n");
		schedule_work(&m->work);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
		atomic_set(&m->active, 0);
		break;
	}
	return 0;
}

static snd_pcm_uframes_t race_pcm_pointer(struct snd_pcm_substream *substream)
{
	return 0;
}

static const struct snd_pcm_ops race_pcm_ops = {
	.open = race_pcm_open,
	.close = race_pcm_close,
	.hw_params = race_pcm_hw_params,
	.prepare = race_pcm_prepare,
	.trigger = race_pcm_trigger,
	.pointer = race_pcm_pointer,
};

static int sndusb_pcm_init(void)
{
	int ret;

	race_pdev = platform_device_register_simple("sndusb_race", -1, NULL, 0);
	if (IS_ERR(race_pdev))
		return PTR_ERR(race_pdev);
	ret = snd_card_new(&race_pdev->dev, 0, "SndUsbRace", THIS_MODULE, 0,
			   &race_card);
	if (ret < 0) {
		pr_err(DRV ": snd_card_new failed: %d\n", ret);
		return ret;
	}
	ret = snd_pcm_new(race_card, "SndUsbRace", 0, 0, 1, &race_pcm_dev);
	if (ret < 0) {
		pr_err(DRV ": snd_pcm_new failed: %d\n", ret);
		snd_card_free(race_card);
		return ret;
	}
	snd_pcm_set_ops(race_pcm_dev, SNDRV_PCM_STREAM_CAPTURE, &race_pcm_ops);
	snd_pcm_lib_preallocate_pages_for_all(race_pcm_dev,
					      SNDRV_DMA_TYPE_CONTINUOUS, NULL,
					      64 * 1024, 64 * 1024);
	ret = snd_card_register(race_card);
	if (ret < 0) {
		pr_err(DRV ": snd_card_register failed: %d\n", ret);
		snd_card_free(race_card);
		return ret;
	}
	pr_info(DRV ": card registered mode=%s safe=%d\n", mode, safe);
	return 0;
}

static int __init sndusb_init(void)
{
	pr_info(DRV ": init mode=%s safe=%d\n", mode, safe);
	return sndusb_pcm_init();
}

static void __exit sndusb_exit(void)
{
	pr_info(DRV ": exit\n");
	if (race_card)
		snd_card_free(race_card);
	if (race_pdev)
		platform_device_unregister(race_pdev);
}

module_init(sndusb_init);
module_exit(sndusb_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("TASCAM US-144MKII C1/C2 synthetic lifetime reproducer");

[-- Attachment #3: pcmtest.c --]
[-- Type: text/plain, Size: 3737 bytes --]

#define _GNU_SOURCE
// SPDX-License-Identifier: GPL-2.0
/*
 * pcmtest.c - guest-side exerciser for sndpci_race.ko.
 *
 * Usage:
 *   pcmtest close [iters]  - open/start/close one playback substream (V4)
 *   pcmtest link  [iters]  - link two playback substreams, close B while
 *                            the A timer callback walks the group (V5)
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <limits.h>
#include <sched.h>
#include <sound/asound.h>

#define DEV "/dev/snd/pcmC0D0c"

static int set_hw_params(int fd)
{
	struct snd_pcm_hw_params p;
	int i, ret;

	memset(&p, 0, sizeof(p));
	for (i = 0; i <= SNDRV_PCM_HW_PARAM_LAST_MASK -
			SNDRV_PCM_HW_PARAM_FIRST_MASK; i++)
		memset(&p.masks[i], 0xff, sizeof(p.masks[i]));
	for (i = 0; i <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
			SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; i++) {
		p.intervals[i].min = 0;
		p.intervals[i].max = UINT_MAX;
		p.intervals[i].integer = 0;
	}
	p.rmask = ~0U;
	ret = ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, &p);
	printf("HW_REFINE ret=%d errno=%d\n", ret, errno);
	if (ret < 0)
		return -1;
	printf("refined: rate=%u ch=%u fmt=%u ps=%u periods=%u bs=%u\n",
	       p.intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min,
	       p.intervals[SNDRV_PCM_HW_PARAM_CHANNELS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min,
	       __builtin_ctz(p.masks[SNDRV_PCM_HW_PARAM_FORMAT].bits[0]),
	       p.intervals[SNDRV_PCM_HW_PARAM_PERIOD_SIZE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min,
	       p.intervals[SNDRV_PCM_HW_PARAM_PERIODS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min,
	       p.intervals[SNDRV_PCM_HW_PARAM_BUFFER_SIZE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min);
	ret = ioctl(fd, SNDRV_PCM_IOCTL_HW_PARAMS, &p);
	if (ret < 0) {
		fprintf(stderr, "HW_PARAMS: %s\n", strerror(errno));
		return -1;
	}
	return 0;
}

static int open_stream(void)
{
	int fd = open(DEV, O_RDWR | O_NONBLOCK);

	if (fd < 0)
		fprintf(stderr, "open %s: %s\n", DEV, strerror(errno));
	return fd;
}

static int prepare_stream(int fd)
{
	if (set_hw_params(fd) < 0)
		return -1;
	if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE, 0) < 0) {
		fprintf(stderr, "PREPARE: %s\n", strerror(errno));
		return -1;
	}
	return 0;
}

static int start_stream(int fd)
{
	if (ioctl(fd, SNDRV_PCM_IOCTL_START, 0) < 0) {
		fprintf(stderr, "START: %s\n", strerror(errno));
		return -1;
	}
	return 0;
}

static int one_close(void)
{
	int fd = open_stream();

	if (fd < 0)
		return -1;
	if (prepare_stream(fd) < 0 || start_stream(fd) < 0) {
		close(fd);
		return -1;
	}
	usleep(10000);
	close(fd);
	return 0;
}

static int one_link(void)
{
	int a = open_stream();
	int b = open_stream();

	if (a < 0 || b < 0)
		return -1;
	if (prepare_stream(a) < 0 || prepare_stream(b) < 0)
		goto out;
	if (ioctl(a, SNDRV_PCM_IOCTL_LINK, b) < 0) {
		fprintf(stderr, "LINK: %s\n", strerror(errno));
		goto out;
	}
	if (start_stream(a) < 0)
		goto out;
	/* Let the A timer callback start walking the linked group. */
	usleep(1500);
	/* Close B while A's callback may be in the group loop. */
	close(b);
	b = -1;
	usleep(1500);
out:
	if (b >= 0)
		close(b);
	if (a >= 0)
		close(a);
	return 0;
}

int main(int argc, char **argv)
{
	cpu_set_t set;

	CPU_ZERO(&set);
	CPU_SET(1, &set);
	sched_setaffinity(0, sizeof(set), &set);
	int i, n = 200;

	if (argc < 2) {
		fprintf(stderr, "usage: %s close|link [iters]\n", argv[0]);
		return 2;
	}
	if (argc > 2)
		n = atoi(argv[2]);
	printf("pcmtest: mode=%s iters=%d\n", argv[1], n);
	for (i = 0; i < n; i++) {
		if (!strcmp(argv[1], "link")) {
			if (one_link() < 0)
				break;
		} else {
			if (one_close() < 0)
				break;
		}
	}
	printf("pcmtest: done i=%d\n", i);
	return 0;
}

[-- Attachment #4: Makefile --]
[-- Type: application/octet-stream, Size: 320 bytes --]

# Build against the running kernel's headers.
# For a KASAN test kernel, set KDIR to that build tree, e.g.:
#   make KDIR=/path/to/linux KASAN=1
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD  := $(shell pwd)

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

obj-m := tascam_poc.o

  parent reply	other threads:[~2026-11-13 12:28 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-27 12:35 usb: devio: usbdev_release() has no barrier against an in-flight async_completed() callback (use-after-free window on struct usb_dev_state)gregkh@linuxfoundation.org 徐晗翔
2026-10-27 14:12 ` Greg KH
2026-11-03 11:21   ` mm/slub: has_pcs_used() reads remote per-CPU sheaf state from flush_all_cpus_locked() without synchronization (data race; KCSAN blind spot: slub.o is uninstrumented) 徐晗翔
2026-11-04  9:41     ` Qing Wang
2026-11-04 10:07       ` Qing Wang
2026-11-03 11:30   ` futex/hrtimer: hrtimer_sleeper::task is read unsynchronized in 16 places on v7.3 -- the accessor series that fixes this is not in 7.3; please make sure it reaches the affected trees (backport nudge + stock-kernel KCSAN evidence) 徐晗翔
2026-11-03 11:48   ` cgroup: fork vs cgroup.procs write race in favordynmods mode -- v7.3 is affected; please make sure bf6fbf46b5ff reaches the stable trees (repro incl. uninstrumented natural hit) 徐晗翔
2026-11-03 14:51     ` Sasha Levin
2026-11-03 11:57   ` net: rtnetlink: rtnl_link_unregister() vs in-flight RTM_GETLINK dump readers -- v7.3 lacks the synchronize_rcu() fix (Fixes: 6b57ff21a310 family); A/B reproduction on stock 7.3 徐晗翔
2026-11-03 15:49     ` Eric Dumazet
2026-11-04 15:03     ` Sasha Levin
2026-11-03 12:07   ` wifi: wilc1000: SDIO/SPI remove destroys the srcu_struct before wiphy_unregister() -- late cfg80211 callbacks write through dangling srcu state (unfixed upstream; controlled + natural Oops) 徐晗翔
2026-11-03 12:10   ` gpio: gpiolib: final put of the gpio_device happens inside the SRCU read critical section on the setup-failure path -- deterministic use-after-free read at guard release (unfixed upstream) 徐晗翔
2026-11-05  8:52     ` Linus Walleij
2026-11-04 12:54   ` soc: qcom: pmic_glink_altmode: fix use-after-free on unbind (no cancel_work_sync for port work and enable_work) 徐晗翔
2026-11-04 13:04     ` Greg KH
2026-11-04 12:57   ` usb: typec: anx7411: unregister partner/altmodes before stopping the IRQ work -- use-after-free, double unregister, orphan partner on remove 徐晗翔
2026-11-04 13:28     ` Greg KH
2026-11-04 12:58   ` usb: typec: ucsi: deadlock on cros_ec unbind -- connector lock held across cancel_delayed_work_sync vs the mode-selection work's unbounded trylock polling 徐晗翔
2026-11-04 13:00   ` usb: typec: stusb160x/rt1719/hd3ss3220: IRQ thread vs remove -- double unregister / use-after-free on the partner and port 徐晗翔
2026-11-04 13:01   ` usb: typec: ucsi: displayport: data race on dp->header/ vdo_data/vdo_size -- work reads them unlocked while writers hold con->lock (VDM mismatch) 徐晗翔
2026-11-04 13:02   ` usb: typec: class: three lifetime/locking gaps around the mux/switch handles and mode_selection (drvdata UAF after provider unbind; no concurrent protocol for set/put; unlocked state_update vs delete) 徐晗翔
2026-11-10 12:56   ` driver core: uevent: netns teardown frees uevent_sock while a tagged uevent is still being broadcast (UAF) 徐晗翔
2026-11-10 13:00   ` 徐晗翔
2026-11-10 18:48     ` Greg KH
2026-11-10 13:05   ` ACPI: CPPC: per-CPU cpc_desc is freed on processor unbind without clearing the published pointer, causing UAF in cpufreq accessors 徐晗翔
2026-11-10 13:07   ` ACPI: CPPC: shared PCC subspace data can be freed while another CPU probes, reads, or tears it down 徐晗翔
2026-11-10 14:47     ` Christian Loehle
2026-11-10 13:11   ` ACPI: ACPICA: Reset can delete an event semaphore while another thread is blocked in Wait 徐晗翔
2026-11-10 13:14   ` power: supply: bq25890: pump-express work can call power_supply_changed after the psy is unregistered 徐晗翔
2026-11-10 13:17   ` power: supply: core: get/set property callbacks can run after unregister and read freed driver data 徐晗翔
2026-11-10 13:18   ` power: supply: core: system-battery enumeration can return an unregistered battery 徐晗翔
2026-11-10 13:21   ` power: supply: core: changed work can run after unregister and use freed LED triggers 徐晗翔
2026-11-10 13:23   ` power: supply: bq24190: IRQ handler can call power_supply_changed after the psy is unregistered 徐晗翔
2026-11-10 13:34   ` 徐晗翔
2026-11-11  7:17   ` genirq: NMI dispatch reads struct irqaction with no quiescence -- use-after-free across free_nmi()'s kfree (x86 verification on the arch-independent core path) 徐晗翔
2026-11-11  7:26   ` genirq: NMI API lacks the request_mutex / dev_id matching / idempotency semantics that free_irq() has -- double free_nmi releases chip PM and module references twice (verified) 徐晗翔
2026-11-11  7:30   ` kernfs: kernfs_drain()'s fast-path decision reads the active count without acquire ordering -- on weakly-ordered architectures the forced ->release()/unmap can be skipped 徐晗翔
2026-11-11 13:41     ` Greg KH
2026-11-13 11:58   ` ALSA: ctxfi: free atimer only after the timer IRQ is quiesced 徐晗翔
2026-11-13 12:03   ` ALSA: ctxfi: do not free a running system timer when timer_delete_sync_try() returns -1 (UAF) 徐晗翔
2026-11-13 12:04   ` ALSA: asihpi: free IRQ before snd_card_free()/HPI delete on HPI6205 removal (UAF) 徐晗翔
2026-11-13 12:06   ` ALSA: asihpi: quiesce PCM timer and IRQ before freeing dpcm on close (UAF) 徐晗翔
2026-11-13 12:15   ` ALSA: pcm: link-group walk in timer callback can use a closed substream's freed runtime (UAF) 徐晗翔
2026-11-13 12:28   ` 徐晗翔 [this message]
2026-11-13 12:29   ` ALSA: usb-audio: us144mkii: queued stop_pcm_work calls snd_pcm_stop() after PCM close and dereferences NULL runtime 徐晗翔
2026-11-13 12:33   ` sched/topology: old domain chains are queued for RCU freeing before the per-CPU pointers are updated, so a late reader can still dereference a freed sched_domain and sched_domain_shared (UAF) 徐晗翔

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=12a3a26a.26361.1a1d4e1ad57.Coremail.xuhx@hust.edu.cn \
    --to=xuhx@hust.edu.cn \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.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

all inboxes | Powered by JetHome®