summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2022-10-11 10:01:47 +0300
committerTakashi Iwai <tiwai@suse.de>2022-10-11 10:02:43 +0300
commit97d917879d7f92df09c3f21fd54609a8bcd654b2 (patch)
tree99dd7e3590f0520dfb1aae4fa3d5ad05cb17c587 /sound/core
parenta70aef7982b012e86dfd39fbb235e76a21ae778a (diff)
downloadlinux-97d917879d7f92df09c3f21fd54609a8bcd654b2.tar.xz
ALSA: oss: Fix potential deadlock at unregistration
We took sound_oss_mutex around the calls of unregister_sound_special() at unregistering OSS devices. This may, however, lead to a deadlock, because we manage the card release via the card's device object, and the release may happen at unregister_sound_special() call -- which will take sound_oss_mutex again in turn. Although the deadlock might be fixed by relaxing the rawmidi mutex in the previous commit, it's safer to move unregister_sound_special() calls themselves out of the sound_oss_mutex, too. The call is race-safe as the function has a spinlock protection by itself. Link: https://lore.kernel.org/r/CAB7eexJP7w1B0mVgDF0dQ+gWor7UdkiwPczmL7pn91xx8xpzOA@mail.gmail.com Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/r/20221011070147.7611-2-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/sound_oss.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 7ed0a2a91035..2751bf2ff61b 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -162,7 +162,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
mutex_unlock(&sound_oss_mutex);
return -ENOENT;
}
- unregister_sound_special(minor);
switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
case SNDRV_MINOR_OSS_PCM:
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO);
@@ -174,12 +173,18 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
break;
}
- if (track2 >= 0) {
- unregister_sound_special(track2);
+ if (track2 >= 0)
snd_oss_minors[track2] = NULL;
- }
snd_oss_minors[minor] = NULL;
mutex_unlock(&sound_oss_mutex);
+
+ /* call unregister_sound_special() outside sound_oss_mutex;
+ * otherwise may deadlock, as it can trigger the release of a card
+ */
+ unregister_sound_special(minor);
+ if (track2 >= 0)
+ unregister_sound_special(track2);
+
kfree(mptr);
return 0;
}