aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-03-24 04:50:15 -0400
committerTakashi Iwai <tiwai@suse.de>2011-03-25 14:22:50 -0400
commita45e3d6b13e97506b616980c0f122c3389bcefa4 (patch)
tree838017dcc314bd25b92c31204a15e6fef8a53f1c
parentb2e65c8e9133218eb28c30e79ddd3d66d4666ba0 (diff)
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>
-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)
848 return -ENOMEM; 848 return -ENOMEM;
849 mfile->file = file; 849 mfile->file = file;
850 mfile->disconnected_f_op = NULL; 850 mfile->disconnected_f_op = NULL;
851 INIT_LIST_HEAD(&mfile->shutdown_list);
851 spin_lock(&card->files_lock); 852 spin_lock(&card->files_lock);
852 if (card->shutdown) { 853 if (card->shutdown) {
853 spin_unlock(&card->files_lock); 854 spin_unlock(&card->files_lock);
@@ -883,6 +884,9 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
883 list_for_each_entry(mfile, &card->files_list, list) { 884 list_for_each_entry(mfile, &card->files_list, list) {
884 if (mfile->file == file) { 885 if (mfile->file == file) {
885 list_del(&mfile->list); 886 list_del(&mfile->list);
887 spin_lock(&shutdown_lock);
888 list_del(&mfile->shutdown_list);
889 spin_unlock(&shutdown_lock);
886 if (mfile->disconnected_f_op) 890 if (mfile->disconnected_f_op)
887 fops_put(mfile->disconnected_f_op); 891 fops_put(mfile->disconnected_f_op);
888 found = mfile; 892 found = mfile;