diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-03-24 04:50:15 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-03-25 14:22:50 -0400 |
commit | a45e3d6b13e97506b616980c0f122c3389bcefa4 (patch) | |
tree | 838017dcc314bd25b92c31204a15e6fef8a53f1c | |
parent | b2e65c8e9133218eb28c30e79ddd3d66d4666ba0 (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.c | 4 |
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; |