diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 7c397b1c9231..ba6cdfe64246 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -75,11 +75,11 @@ static inline void snd_compr_task_free_all(struct snd_compr_stream *stream) { } static int snd_compr_open(struct inode *inode, struct file *f) { struct snd_compr *compr; - struct snd_compr_file *data; - struct snd_compr_runtime *runtime; + struct snd_compr_file *data = NULL; + struct snd_compr_runtime *runtime = NULL; enum snd_compr_direction dirn; int maj = imajor(inode); - int ret; + int ret = 0; if ((f->f_flags & O_ACCMODE) == O_WRONLY) dirn = SND_COMPRESS_PLAYBACK; @@ -101,16 +101,21 @@ static int snd_compr_open(struct inode *inode, struct file *f) return -ENODEV; } + if (!try_module_get(compr->card->module)) { + snd_card_unref(compr->card); + return -EFAULT; + } + if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); - snd_card_unref(compr->card); - return -EINVAL; + ret = -EINVAL; + goto __error; } data = kzalloc_obj(*data); if (!data) { - snd_card_unref(compr->card); - return -ENOMEM; + ret = -ENOMEM; + goto __error; } INIT_DELAYED_WORK(&data->stream.error_work, error_delayed_work); @@ -121,9 +126,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) data->stream.device = compr; runtime = kzalloc_obj(*runtime); if (!runtime) { - kfree(data); - snd_card_unref(compr->card); - return -ENOMEM; + ret = -ENOMEM; + goto __error; } runtime->state = SNDRV_PCM_STATE_OPEN; init_waitqueue_head(&runtime->sleep); @@ -134,9 +138,12 @@ static int snd_compr_open(struct inode *inode, struct file *f) f->private_data = (void *)data; scoped_guard(mutex, &compr->lock) ret = compr->ops->open(&data->stream); + +__error: if (ret) { kfree(runtime); kfree(data); + module_put(compr->card->module); } snd_card_unref(compr->card); return ret; @@ -164,6 +171,7 @@ static int snd_compr_free(struct inode *inode, struct file *f) data->stream.ops->free(&data->stream); if (!data->stream.runtime->dma_buffer_p) kfree(data->stream.runtime->buffer); + module_put(data->stream.device->card->module); kfree(data->stream.runtime); kfree(data); return 0;