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: pcm: link-group walk in timer callback can use a closed substream's freed runtime (UAF)
Date: Fri, 13 Nov 2026 20:15:08 +0800 (GMT+08:00) [thread overview]
Message-ID: <7117f13e.2631e.1a1d4d54236.Coremail.xuhx@hust.edu.cn> (raw)
In-Reply-To: <2026102727-data-sequel-ce41@gregkh>
[-- Attachment #1: Type: text/plain, Size: 4714 bytes --]
`snd_card_asihpi_timer_function()` walks the PCM link group with
`snd_pcm_group_for_each_entry()` and dereferences each member's
`s->runtime->private_data`. That macro is a plain `list_for_each_entry()`;
the callback holds no group reference and no group lock. Close of another
linked substream can unlink/free the group and detach/free that substream's
runtime and `dpcm`, leaving the timer callback with a stale `s`/runtime
pointer. This is reachable from user space through
`SNDRV_PCM_IOCTL_LINK` plus close, on hardware whose driver supports PCM
linking (asihpi does).
The detailed description:
* Test environment / affected version
Linux 7.3.0 source plus a QEMU/KASAN fake-PCM harness. No ASI6205 hardware
was available; the harness reproduces the core group traversal and close
ordering, with the asihpi callback's exact
`snd_pcm_group_for_each_entry()` pattern.
* Mechanism
The group loops are at `sound/pci/asihpi/asihpi.c:729-735` and `821-827`.
They read `s->runtime->private_data` (and in one path `dma_area`) and call
`snd_pcm_period_elapsed(s)`. The macro is
`include/sound/pcm.h:694`:
#define snd_pcm_group_for_each_entry(s, substream) \
list_for_each_entry(s, &substream->group->substreams, link_list)
`snd_pcm_stream_lock_irq()` (`sound/core/pcm_native.c:140-144`) locks
`substream->self_group`, not the group that the timer callback walks.
`snd_pcm_unlink()` (`pcm_native.c:2370-2402`) takes
`snd_pcm_link_rwsem` and the group lock, removes the closing substream,
relinks the remaining streams, and may `kfree(group)`.
`snd_pcm_release_substream()` (`pcm_native.c:2785-2805`) calls
`pcm_release_private()` -> `snd_pcm_unlink()` at 2779-2783 before
`snd_pcm_detach_substream()` frees the runtime and `dpcm`.
A timer callback that already loaded member `s` or `s->runtime` can run
after B's unlink/detach. It may then read freed `runtime`, freed
`private_data`, or a freed group list node; `snd_pcm_period_elapsed(s)`
additionally takes the stale substream.
* Why existing synchronization does not close the window
`snd_pcm_stop()` does transiently take a group reference through
`snd_pcm_action()` -> `snd_pcm_stream_group_ref()` (`pcm_native.c:1378-1427`)
and group lock, but it drops the reference after the STOP action. The
asihpi timer callback is not part of that action and holds no group
reference. Taking `snd_pcm_stream_lock_irq(A)` in the callback would only
lock A's `self_group`; it would not pin B or the group. The group can be
freed while the callback holds a raw member pointer.
* Trigger model
Two capture substreams A and B, same PCM and runtime state; user does
`SNDRV_PCM_IOCTL_LINK` then starts A. While A's timer callback is walking
the group, user closes B. `SNDRV_PCM_IOCTL_LINK` is available to a local
user with the PCM device open; no special privilege is needed beyond access
to the PCM. Consequence: UAF in timer context, crash or memory corruption.
* How to run the PoC
The harness is self-contained and does not need ASI6205 hardware: it creates
a fake ALSA card with two capture substreams. The tested configuration was
7.3.0 with KASAN and 4 vCPU; a uniprocessor run may not overlap.
Build against the target kernel build tree:
printf 'obj-m := sndpci_race.o\n' > Kbuild
make -C <kernel-build-dir> M=$PWD modules
gcc -static -O2 -I<kernel-source>/include/uapi -o pcmtest pcmtest.c
Put `sndpci_race.ko` and `pcmtest` into the guest initramfs/rootfs, boot the
target kernel (QEMU/KVM recommended), then run as root:
insmod sndpci_race.ko mode=pcm
./pcmtest link 200
dmesg | grep -E 'BUG: KASAN|race_pcm_timer|victim use'
In the minimal guest the fake card enumerates as card 0 and `pcmtest` opens
`/dev/snd/pcmC0D0c`. If the test machine already has another sound card,
adjust `DEV` in `pcmtest.c` or use the QEMU initramfs. Expected result:
32 KASAN reports with `slab-use-after-free in race_pcm_timer` and about 114
`victim use` lines.
* Suggested direction
This needs a core/lifetime fix, not just an asihpi timer fix. Possible
directions: make group traversal safe against concurrent unlink (group
reference or RCU-protected/atomic-safe iterator that pins each member's
runtime), or provide a driver API that snapshots/refcounts members before
the callback walks them. On the asihpi side, quiesce the timer/IRQ before
allowing the linked substream to detach. Adding only
`snd_pcm_stream_lock_irq(A)` is not sufficient because it locks A's
`self_group`, not the group being walked.
Please keep me in Cc; I am not subscribed to the lists.
Regards,
Hanxiang Xu
xuhx@hust.edu.cn
[-- Attachment #2: sndpci_race.c --]
[-- Type: text/plain, Size: 9729 bytes --]
// SPDX-License-Identifier: GPL-2.0
/*
* sndpci_race.c - minimal ALSA/kernel lifetime-race reproducers for the
* sound/pci manual-review cases V3/V4/V5.
*
* The module deliberately reproduces the *lifetime patterns* used by
* ctxfi/asihpi, using only exported ALSA core and timer APIs. It is not a
* ctxfi/asihpi emulator: those drivers need hardware that this QEMU does not
* provide. The purpose is to test whether the core/API windows identified in
* the report are real on an instrumented KASAN kernel.
*
* modes:
* v3 - timer_delete_sync_try() returns -1 while the callback runs on
* another CPU; free the object anyway (ctxfi system-timer pattern).
* pcm - create a fake ALSA card with two playback substreams. The guest
* program pcmtest then exercises close (V4) or link+close (V5).
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/cpumask.h>
#include <linux/sched.h>
#include <linux/container_of.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#define DRV "sndpci_race"
#define COOKIE 0x5a5a1234deadbeefULL
static char *mode = "pcm";
module_param(mode, charp, 0444);
static bool safe;
module_param(safe, bool, 0444);
MODULE_PARM_DESC(mode, "v3 or pcm");
/* ------------------------------------------------------------------ */
/* V3: timer_delete_sync_try() ignored -1 */
/* ------------------------------------------------------------------ */
struct v3_obj {
struct timer_list timer;
u64 cookie;
struct task_struct *thread;
};
static void v3_callback(struct timer_list *t)
{
struct v3_obj *v = container_of(t, struct v3_obj, timer);
/* Keep the callback alive long enough for the freeing CPU to run. */
mdelay(20);
pr_info(DRV ": v3 callback cookie=%#llx\n", v->cookie);
/* Second read after the delay: the object may already be freed. */
if (v->cookie == COOKIE)
pr_info(DRV ": v3 callback read-after-free survived\n");
}
static int v3_thread(void *arg)
{
struct v3_obj *v;
int i, ret;
for (i = 0; i < 8; i++) {
v = kzalloc(sizeof(*v), GFP_KERNEL);
if (!v)
return -ENOMEM;
v->cookie = COOKIE;
timer_setup(&v->timer, v3_callback, 0);
/* Pin the callback to CPU0; this thread runs on CPU1. */
add_timer_on(&v->timer, 0);
usleep_range(2000, 3000);
ret = timer_delete_sync_try(&v->timer);
pr_info(DRV ": v3 iter=%d delete_sync_try=%d\n", i, ret);
if (ret == -1) {
/* BUG: callback is running on CPU0; free it anyway. */
if (safe)
timer_delete_sync(&v->timer);
kfree(v);
} else {
timer_delete_sync(&v->timer);
kfree(v);
}
usleep_range(60000, 70000);
}
pr_info(DRV ": v3 done\n");
return 0;
}
/* ------------------------------------------------------------------ */
/* V4/V5: fake ALSA PCM with a driver-private dpcm and a timer */
/* ------------------------------------------------------------------ */
struct race_pcm {
struct timer_list timer;
struct snd_pcm_substream *substream;
u64 cookie;
bool respawn;
bool active;
};
static struct snd_card *race_card;
static struct platform_device *race_pdev;
static struct snd_pcm *race_pcm_dev;
static void race_pcm_timer(struct timer_list *t)
{
struct race_pcm *dpcm = container_of(t, struct race_pcm, timer);
struct snd_pcm_substream *s;
struct snd_pcm_runtime *victim_rt = NULL;
u64 cookie;
if (!dpcm->active)
return;
pr_info(DRV ": timer start dpcm=%px\n", dpcm);
/*
* V5 pattern: walk the link group without the group lock and read
* each member's runtime/private_data. V4 uses the same callback for
* the current stream; the delay widens the close/free window.
*/
cookie = dpcm->cookie;
if (cookie == COOKIE && dpcm->substream && dpcm->substream->runtime) {
snd_pcm_group_for_each_entry(s, dpcm->substream) {
struct snd_pcm_runtime *rt = READ_ONCE(s->runtime);
struct race_pcm *d = NULL;
if (rt)
d = READ_ONCE(rt->private_data);
if (d && d->cookie == COOKIE) {
/* Force the compiler to keep the load. */
barrier();
}
if (rt) {
(void)READ_ONCE(rt->dma_area);
if (s != dpcm->substream && !victim_rt)
victim_rt = rt;
}
/* A real driver also reports elapsed periods. */
if (rt)
snd_pcm_period_elapsed(s);
}
}
/* Widen the window between the callback's load and the free. */
mdelay(20);
if (victim_rt) {
struct race_pcm *d = READ_ONCE(victim_rt->private_data);
pr_info(DRV ": victim use rt=%px d=%px\n", victim_rt, d);
(void)READ_ONCE(victim_rt->dma_area);
}
pr_info(DRV ": timer end dpcm=%px\n", dpcm);
if (dpcm->respawn) {
if (!timer_pending(&dpcm->timer))
add_timer_on(&dpcm->timer, 0);
else
mod_timer(&dpcm->timer, jiffies + 1);
}
}
static void race_pcm_free(struct snd_pcm_runtime *runtime)
{
struct race_pcm *dpcm = runtime->private_data;
pr_info(DRV ": pcm private_free dpcm=%px\n", dpcm);
if (safe)
timer_shutdown_sync(&dpcm->timer);
kfree(dpcm);
}
static int race_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct race_pcm *dpcm;
dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
if (!dpcm)
return -ENOMEM;
dpcm->substream = substream;
dpcm->cookie = COOKIE;
timer_setup(&dpcm->timer, race_pcm_timer, 0);
runtime->private_data = dpcm;
runtime->private_free = race_pcm_free;
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 ": pcm open sub=%px dpcm=%px\n", substream, dpcm);
return 0;
}
static int race_pcm_close(struct snd_pcm_substream *substream)
{
pr_info(DRV ": pcm .close sub=%px\n", substream);
return 0;
}
static int race_pcm_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
pr_info(DRV ": pcm ioctl cmd=%u\n", cmd);
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
static int race_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
pr_info(DRV ": hw_params rate=%u ch=%u fmt=%u period_bytes=%u buffer_bytes=%u\n",
params_rate(params), params_channels(params), params_format(params),
params_period_bytes(params), params_buffer_bytes(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 race_pcm *dpcm = substream->runtime->private_data;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
if (substream != race_pcm_dev->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
break;
dpcm->active = true;
dpcm->respawn = true;
if (!timer_pending(&dpcm->timer))
add_timer_on(&dpcm->timer, 0);
else
mod_timer(&dpcm->timer, jiffies + 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
dpcm->active = false;
dpcm->respawn = false;
/* Deliberately not timer_delete_sync(): mirrors asihpi. */
timer_delete(&dpcm->timer);
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,
.ioctl = race_pcm_ioctl,
.hw_params = race_pcm_hw_params,
.prepare = race_pcm_prepare,
.trigger = race_pcm_trigger,
.pointer = race_pcm_pointer,
};
static int __init sndpci_init(void)
{
struct task_struct *t;
int ret;
pr_info(DRV ": init mode=%s\n", mode);
if (!strcmp(mode, "v3")) {
t = kthread_create(v3_thread, NULL, "sndpci_v3");
if (IS_ERR(t))
return PTR_ERR(t);
kthread_bind(t, 1);
wake_up_process(t);
return 0;
}
race_pdev = platform_device_register_simple("sndpci_race", -1, NULL, 0);
if (IS_ERR(race_pdev))
return PTR_ERR(race_pdev);
ret = snd_card_new(&race_pdev->dev, 0, "SndPciRace", 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, "SndPciRace", 0, 0, 2, &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 = 0;
pr_info(DRV ": managed_buffer ret=%d dma_type=%d area=%px bytes=%zu\n", ret,
race_pcm_dev->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer.dev.type,
race_pcm_dev->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer.area,
race_pcm_dev->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer.bytes);
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\n");
return 0;
}
static void __exit sndpci_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(sndpci_init);
module_exit(sndpci_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("sound/pci lifetime-race reproducer (V3/V4/V5)");
[-- 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;
}
next prev parent reply other threads:[~2026-11-13 12:15 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 ` 徐晗翔 [this message]
2026-11-13 12:28 ` ALSA: usb-audio: us144mkii: PCM close frees runtime while playback/feedback URB completion and capture work still use it (UAF) 徐晗翔
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=7117f13e.2631e.1a1d4d54236.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®