summary refs log tree commit diff
path: root/sound/core/init.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-03-24 09:50:15 +0100
committerTakashi Iwai <tiwai@suse.de>2011-03-25 19:22:50 +0100
commita45e3d6b13e97506b616980c0f122c3389bcefa4 (patch)
tree838017dcc314bd25b92c31204a15e6fef8a53f1c /sound/core/init.c
parentb2e65c8e9133218eb28c30e79ddd3d66d4666ba0 (diff)
downloadlinux-a45e3d6b13e97506b616980c0f122c3389bcefa4.tar.gz
ALSA: Fix yet another race in disconnection
This patch fixes a race between snd_card_file_remove() and
snd_card_disconnect().  When the card is added to shutdown_files list
in snd_card_disconnect(), but it's freed in snd_card_file_remove() at
the same time, the shutdown_files list gets corrupted.  The list member
must be freed in snd_card_file_remove() as well.

Reported-and-tested-by: Russ Dill <russ.dill@gmail.com>
Cc: <stable@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/init.c')
-rw-r--r--sound/core/init.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/sound/core/init.c b/sound/core/init.c
index 3e65da21a08c..a0080aa45ae9 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -848,6 +848,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
 		return -ENOMEM;
 	mfile->file = file;
 	mfile->disconnected_f_op = NULL;
+	INIT_LIST_HEAD(&mfile->shutdown_list);
 	spin_lock(&card->files_lock);
 	if (card->shutdown) {
 		spin_unlock(&card->files_lock);
@@ -883,6 +884,9 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
 	list_for_each_entry(mfile, &card->files_list, list) {
 		if (mfile->file == file) {
 			list_del(&mfile->list);
+			spin_lock(&shutdown_lock);
+			list_del(&mfile->shutdown_list);
+			spin_unlock(&shutdown_lock);
 			if (mfile->disconnected_f_op)
 				fops_put(mfile->disconnected_f_op);
 			found = mfile;