ALSA: compress: Don't embed device

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>
This commit is contained in:
Takashi Iwai 2023-08-16 18:02:49 +02:00
parent ea29a02fd8
commit b53a41ee9c
2 changed files with 11 additions and 7 deletions

View File

@ -148,7 +148,7 @@ struct snd_compr_ops {
*/ */
struct snd_compr { struct snd_compr {
const char *name; const char *name;
struct device dev; struct device *dev;
struct snd_compr_ops *ops; struct snd_compr_ops *ops;
void *private_data; void *private_data;
struct snd_card *card; struct snd_card *card;

View File

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