ALSA: compress: Don't embed device
authorTakashi Iwai <tiwai@suse.de>
Wed, 16 Aug 2023 16:02:49 +0000 (18:02 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 17 Aug 2023 07:24:15 +0000 (09:24 +0200)
Embedding the struct device to snd_compr object may result in UAF when
the delayed kobj release is used.  Like other devices, let's detach
the struct device from the snd_compr by allocating dynamically via
snd_device_alloc().

Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Curtis Malainey <cujomalainey@chromium.org>
Tested-by: Curtis Malainey <cujomalainey@chromium.org>
Link: https://lore.kernel.org/r/20230816160252.23396-7-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/compress_driver.h
sound/core/compress_offload.c

index d91289c6f00e665740f1d13954e5283e74b837d0..bcf872c17dd3345b3306d955335ee569939385d7 100644 (file)
@@ -148,7 +148,7 @@ struct snd_compr_ops {
  */
 struct snd_compr {
        const char *name;
-       struct device dev;
+       struct device *dev;
        struct snd_compr_ops *ops;
        void *private_data;
        struct snd_card *card;
index 30f73097447ba89a6a550357003605eaaf8dab4d..619371aa9964dcb23f24bbae1658fb891b11ca20 100644 (file)
@@ -546,7 +546,7 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
                if (stream->runtime->dma_buffer_p) {
 
                        if (buffer_size > stream->runtime->dma_buffer_p->bytes)
-                               dev_err(&stream->device->dev,
+                               dev_err(stream->device->dev,
                                                "Not enough DMA buffer");
                        else
                                buffer = stream->runtime->dma_buffer_p->area;
@@ -1070,7 +1070,7 @@ static int snd_compress_dev_register(struct snd_device *device)
        /* register compressed device */
        ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS,
                                  compr->card, compr->device,
-                                 &snd_compr_file_ops, compr, &compr->dev);
+                                 &snd_compr_file_ops, compr, compr->dev);
        if (ret < 0) {
                pr_err("snd_register_device failed %d\n", ret);
                return ret;
@@ -1084,7 +1084,7 @@ static int snd_compress_dev_disconnect(struct snd_device *device)
        struct snd_compr *compr;
 
        compr = device->device_data;
-       snd_unregister_device(&compr->dev);
+       snd_unregister_device(compr->dev);
        return 0;
 }
 
@@ -1158,7 +1158,7 @@ static int snd_compress_dev_free(struct snd_device *device)
 
        compr = device->device_data;
        snd_compress_proc_done(compr);
-       put_device(&compr->dev);
+       put_device(compr->dev);
        return 0;
 }
 
@@ -1189,12 +1189,16 @@ int snd_compress_new(struct snd_card *card, int device,
 
        snd_compress_set_id(compr, id);
 
-       snd_device_initialize(&compr->dev, card);
-       dev_set_name(&compr->dev, "comprC%iD%i", card->number, device);
+       ret = snd_device_alloc(&compr->dev, card);
+       if (ret)
+               return ret;
+       dev_set_name(compr->dev, "comprC%iD%i", card->number, device);
 
        ret = snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
        if (ret == 0)
                snd_compress_proc_init(compr);
+       else
+               put_device(compr->dev);
 
        return ret;
 }