[PATCH 6.19 244/844] ALSA: mixer: oss: Add card disconnect checkpoints

From: Sasha Levin

Date: Sat Feb 28 2026 - 13:43:59 EST


From: Takashi Iwai <tiwai@xxxxxxx>

[ Upstream commit 084d5d44418148662365eced3e126ad1a81ee3e2 ]

ALSA OSS mixer layer calls the kcontrol ops rather individually, and
pending calls might be not always caught at disconnecting the device.

For avoiding the potential UAF scenarios, add sanity checks of the
card disconnection at each entry point of OSS mixer accesses. The
rwsem is taken just before that check, hence the rest context should
be covered by that properly.

Link: https://patch.msgid.link/20260209121212.171430-1-tiwai@xxxxxxx
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
sound/core/oss/mixer_oss.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 8d2d46d03301b..f4ad0bfb4dac6 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -523,6 +523,8 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
@@ -557,6 +559,8 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
@@ -618,6 +622,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
@@ -656,6 +662,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
if (numid == ID_UNKNOWN)
return;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return;
kctl = snd_ctl_find_numid(card, numid);
if (!kctl)
return;
@@ -796,6 +804,8 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
if (uinfo == NULL || uctl == NULL)
return -ENOMEM;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return -ENODEV;
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (!kctl)
return -ENOENT;
@@ -839,6 +849,8 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
if (uinfo == NULL || uctl == NULL)
return -ENOMEM;
guard(rwsem_read)(&card->controls_rwsem);
+ if (card->shutdown)
+ return -ENODEV;
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
if (!kctl)
return -ENOENT;
@@ -885,6 +897,8 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl
if (!info)
return -ENOMEM;
scoped_guard(rwsem_read, &card->controls_rwsem) {
+ if (card->shutdown)
+ return -ENODEV;
kcontrol = snd_mixer_oss_test_id(mixer, name, index);
if (kcontrol == NULL)
return 0;
@@ -1006,6 +1020,8 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
if (snd_mixer_oss_build_test_all(mixer, ptr, &slot))
return 0;
guard(rwsem_read)(&mixer->card->controls_rwsem);
+ if (mixer->card->shutdown)
+ return -ENODEV;
kctl = NULL;
if (!ptr->index)
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
--
2.51.0