diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-10-16 15:05:59 +0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-10-30 14:07:10 +0400 |
commit | a0830dbd4e42b38aefdf3fb61ba5019a1a99ea85 (patch) | |
tree | 4dc74b708a07b56d12ed72a34d0a2e0cb8c8b9d4 /sound/core/compress_offload.c | |
parent | 888ea7d5ac6815ba16b3b3a20f665a92c7af6724 (diff) | |
download | linux-a0830dbd4e42b38aefdf3fb61ba5019a1a99ea85.tar.xz |
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/compress_offload.c')
-rw-r--r-- | sound/core/compress_offload.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index c40ae573346d..ad11dc994792 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f) if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); + snd_card_unref(compr->card); return -EINVAL; } data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) + if (!data) { + snd_card_unref(compr->card); return -ENOMEM; + } data->stream.ops = compr->ops; data->stream.direction = dirn; data->stream.private_data = compr->private_data; @@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); if (!runtime) { kfree(data); + snd_card_unref(compr->card); return -ENOMEM; } runtime->state = SNDRV_PCM_STATE_OPEN; @@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) kfree(runtime); kfree(data); } - return ret; + snd_card_unref(compr->card); + return 0; } static int snd_compr_free(struct inode *inode, struct file *f) |