Skip to content

Commit 97d9178

Browse files
committed
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: <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent a70aef7 commit 97d9178

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

sound/core/sound_oss.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
162162
mutex_unlock(&sound_oss_mutex);
163163
return -ENOENT;
164164
}
165-
unregister_sound_special(minor);
166165
switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
167166
case SNDRV_MINOR_OSS_PCM:
168167
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)
174173
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
175174
break;
176175
}
177-
if (track2 >= 0) {
178-
unregister_sound_special(track2);
176+
if (track2 >= 0)
179177
snd_oss_minors[track2] = NULL;
180-
}
181178
snd_oss_minors[minor] = NULL;
182179
mutex_unlock(&sound_oss_mutex);
180+
181+
/* call unregister_sound_special() outside sound_oss_mutex;
182+
* otherwise may deadlock, as it can trigger the release of a card
183+
*/
184+
unregister_sound_special(minor);
185+
if (track2 >= 0)
186+
unregister_sound_special(track2);
187+
183188
kfree(mptr);
184189
return 0;
185190
}

0 commit comments

Comments
 (0)