summaryrefslogtreecommitdiffstats
path: root/sound/core/oss
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-10-16 13:05:59 +0200
committerTakashi Iwai <tiwai@suse.de>2012-10-30 11:07:10 +0100
commita0830dbd4e42b38aefdf3fb61ba5019a1a99ea85 (patch)
tree4dc74b708a07b56d12ed72a34d0a2e0cb8c8b9d4 /sound/core/oss
parentALSA: usb-audio: Fix races at disconnection in mixer_quirks.c (diff)
downloadlinux-a0830dbd4e42b38aefdf3fb61ba5019a1a99ea85.tar.xz
linux-a0830dbd4e42b38aefdf3fb61ba5019a1a99ea85.zip
ALSA: Add a reference counter to card instance
For more strict protection for wild disconnections, a refcount is introduced to the card instance, and let it up/down when an object is referred via snd_lookup_*() in the open ops. The free-after-last-close check is also changed to check this refcount instead of the empty list, too. Reported-by: Matthieu CASTET <matthieu.castet@parrot.com> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/oss')
-rw-r--r--sound/core/oss/mixer_oss.c10
-rw-r--r--sound/core/oss/pcm_oss.c2
2 files changed, 10 insertions, 2 deletions
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 29f6ded02555..a9a2e63c0222 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
SNDRV_OSS_DEVICE_TYPE_MIXER);
if (card == NULL)
return -ENODEV;
- if (card->mixer_oss == NULL)
+ if (card->mixer_oss == NULL) {
+ snd_card_unref(card);
return -ENODEV;
+ }
err = snd_card_file_add(card, file);
- if (err < 0)
+ if (err < 0) {
+ snd_card_unref(card);
return err;
+ }
fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
if (fmixer == NULL) {
snd_card_file_remove(card, file);
+ snd_card_unref(card);
return -ENOMEM;
}
fmixer->card = card;
@@ -68,6 +73,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
if (!try_module_get(card->module)) {
kfree(fmixer);
snd_card_file_remove(card, file);
+ snd_card_unref(card);
return -EFAULT;
}
return 0;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 08fde0060fd9..2529e01538e9 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2457,6 +2457,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
__error2:
snd_card_file_remove(pcm->card, file);
__error1:
+ if (pcm)
+ snd_card_unref(pcm->card);
return err;
}