diff options
| author | Cen Zhang <zzzccc427@gmail.com> | 2026-10-19 18:29:33 +0800 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2026-10-19 16:39:50 +0200 |
| commit | bb4834d5242c4829c0d8467ee68eb25a9bafc38d (patch) | |
| tree | 12569337d48e8d46f4b53e7653cb35d9102734bc /tools/lib/python | |
| parent | 8b479b265301e97bfbec0ef25de1c1f7eb4d2f74 (diff) | |
ALSA: pcm: Protect channel-map reads against runtime detach
Channel-map controls remain accessible between PCM opens. In-tree HDA
code publishes the generic controls through add_std_chmaps(), so a
SNDRV_CTL_IOCTL_ELEM_READ can overlap the final close of the same PCM
substream.
pcm_chmap_ctl_get() checks substream->runtime and later reads its channel
count. Final close clears and frees that runtime under pcm->open_mutex,
while the control callback holds only controls_rwsem:
Control GET Final PCM close
----------- ---------------
snd_ctl_elem_read()
down_read(controls_rwsem)
pcm_chmap_ctl_get()
check substream->runtime
lock(pcm->open_mutex)
snd_pcm_release_substream()
snd_pcm_detach_substream()
substream->runtime = NULL
kfree(runtime)
unlock(pcm->open_mutex)
substream->runtime->channels
NULL or freed-pointer access
up_read(controls_rwsem)
Reloading the cleared field can fault through NULL, while retaining the
old pointer can access freed storage. controls_rwsem keeps the control
alive, but does not serialize the matching PCM close.
Copy the channel count under open_mutex and use that scalar for the map
lookup. Use trylock with -EBUSY because snd_pcm_dev_disconnect() takes
open_mutex before removing controls under controls_rwsem; blocking in
the reverse order from GET could deadlock.
Fixes: 2d3391ec0ecc ("ALSA: PCM: channel mapping API implementation")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-0b5d6bc7124d0b921f2c-v4-b9738bdeab8823999181@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'tools/lib/python')
0 files changed, 0 insertions, 0 deletions
