]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ALSA: mixer: oss: Add card disconnect checkpoints
authorTakashi Iwai <tiwai@suse.de>
Mon, 9 Feb 2026 12:12:11 +0000 (13:12 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 9 Feb 2026 12:29:43 +0000 (13:29 +0100)
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@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/oss/mixer_oss.c

index 8d2d46d03301bdc4e1061491d998bce296506100..f4ad0bfb4dac605fa3bab05192497da4971fc37c 100644 (file)
@@ -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);