]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ALSA: compress: Fix task creation error unwind
authorCássio Gabriel <cassiogabrielcontato@gmail.com>
Mon, 15 Jun 2026 13:37:26 +0000 (10:37 -0300)
committerTakashi Iwai <tiwai@suse.de>
Wed, 17 Jun 2026 09:04:10 +0000 (11:04 +0200)
snd_compr_task_new() allocates the driver task before validating the
returned DMA buffers and reserving file descriptors. When either of
those later steps fails, the core frees its task wrapper and DMA-buffer
references without calling the driver's task_free() callback. Any
driver resources allocated by task_create() are therefore leaked.

The dual-fd allocation path also jumps to cleanup without storing the
negative get_unused_fd_flags() result in retval. Since retval still
contains the successful task_create() return value, TASK_CREATE can
incorrectly report success although the task was discarded.

Preserve the fd allocation errors and call task_free() when failure
occurs after a successful task_create() callback.

Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode")
Fixes: 3d3f43fab4cf ("ALSA: compress_offload: improve file descriptors installation for dma-buf")
Cc: stable@vger.kernel.org
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260615-alsa-compress-task-unwind-v1-1-39e8ad3ddb27@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/compress_offload.c

index fd63d219bf86654ca243a516eab9a5843eddb042..ea699491f0c36f1580bd073be28f4438a7939d51 100644 (file)
@@ -1083,15 +1083,18 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_
           file descriptors are allocated before fd_install() */
        if (!task->input || !task->input->file || !task->output || !task->output->file) {
                retval = -EINVAL;
-               goto cleanup;
+               goto free_driver_task;
        }
        fd_i = get_unused_fd_flags(O_WRONLY|O_CLOEXEC);
-       if (fd_i < 0)
-               goto cleanup;
+       if (fd_i < 0) {
+               retval = fd_i;
+               goto free_driver_task;
+       }
        fd_o = get_unused_fd_flags(O_RDONLY|O_CLOEXEC);
        if (fd_o < 0) {
+               retval = fd_o;
                put_unused_fd(fd_i);
-               goto cleanup;
+               goto free_driver_task;
        }
        /* keep dmabuf reference until freed with task free ioctl */
        get_dma_buf(task->input);
@@ -1103,6 +1106,8 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_
        list_add_tail(&task->list, &stream->runtime->tasks);
        stream->runtime->total_tasks++;
        return 0;
+free_driver_task:
+       stream->ops->task_free(stream, task);
 cleanup:
        snd_compr_task_free(task);
        return retval;