diff options
| author | Takashi Iwai <tiwai@suse.de> | 2026-10-15 09:18:09 +0200 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2026-10-15 12:26:09 +0200 |
| commit | 91d0048a97e0fdc0a071caa0ba59e659bc6f84df (patch) | |
| tree | 3e4b674418e20a8a10b23c85dff493e5e48070b3 /include | |
| parent | 85e8c5f933ee3dbc9d061e121237797e9fa05315 (diff) | |
ALSA: pcm: Add refcount for races between drain and unlink
We added a workaround for the case where a linked substream gets
unlinked during the drain operation by another substream of the same
linked group in the commit 9b1dbd69ba6f ("ALSA: pcm: fix
use-after-free on linked stream runtime in snd_pcm_drain()").
There, we just cached the parameters of the draining substream for
avoiding UAF.
Then, we check the draining substream (to_check) again in the loop and
remove it from the queue only when it's still present. It means,
however, that the wait queue entry won't be removed if the substream
went out of the link beforehand, hence a stale wq entry remains.
Later on, this can be woken up, and this may hit a UAF, too.
The problem surfaced more due to the recent change to call
snd_pcm_unlink() earlier.
For properly handling both cases above, in this patch, we introduce a
refcount to the snd_pcm_runtime that indicates the substream is being
accessed / used, then at snd_pcm_release_substream(), it's synced
before the actual resource release via snd_refcount_sync(). This
guarantees that the accessors are finished, and safe to release
memories. Along with the introduction of a refcount, the comments and
the code changes by the former fix were partially reverted as they
don't fit with the updated code flow any longer.
Last but not least, the setup of wait queue entry and
prepare_to_wait() call are moved before the group unref. With this
change, we can avoid the race between the enqueue and the wakeup, too.
Fixes: 9b1dbd69ba6f ("ALSA: pcm: fix use-after-free on linked stream runtime in snd_pcm_drain()")
Link: https://patch.msgid.link/20261015071838.31082-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'include')
| -rw-r--r-- | include/sound/pcm.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 02d8689354c4..1cf511f8d880 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -8,6 +8,7 @@ * Abramo Bagnara <abramo@alsa-project.org> */ +#include <sound/core.h> #include <sound/asound.h> #include <sound/memalloc.h> #include <sound/minors.h> @@ -414,6 +415,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t twake; /* do transfer (!poll) wakeup if non-zero */ wait_queue_head_t sleep; /* poll sleep */ wait_queue_head_t tsleep; /* transfer sleep */ + struct snd_refcount refcnt; /* refcount for draining, etc */ struct snd_fasync *fasync; bool stop_operating; /* sync_stop will be called */ struct mutex buffer_mutex; /* protect for buffer changes */ |
