ALSA: control: Don't embed ctl_dev
Embedding the ctl_dev in the snd_card object may result in UAF when the delayed kobj release is used; at the delayed kobj release, it still accesses the struct device itself while the card memory (that embeds the struct device) may be already gone. As a workaround, detach the struct device from the card object by allocating via the new snd_device_alloc() helper. The rest are just replacing ctl_dev access to the pointer. This is based on the fix Curtis posted initially. In this patch, the changes are split and use the new helper function instead. Link: https://lore.kernel.org/r/20230801171928.1460120-1-cujomalainey@chromium.org 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-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
7f018db19b
commit
6a66b01de4
@ -96,7 +96,7 @@ struct snd_card {
|
||||
private data */
|
||||
struct list_head devices; /* devices */
|
||||
|
||||
struct device ctl_dev; /* control device */
|
||||
struct device *ctl_dev; /* control device */
|
||||
unsigned int last_numid; /* last used numeric ID */
|
||||
struct rw_semaphore controls_rwsem; /* controls lock (list and values) */
|
||||
rwlock_t ctl_files_rwlock; /* ctl_files list lock */
|
||||
|
@ -2389,7 +2389,7 @@ static int snd_ctl_dev_register(struct snd_device *device)
|
||||
int err;
|
||||
|
||||
err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
|
||||
&snd_ctl_f_ops, card, &card->ctl_dev);
|
||||
&snd_ctl_f_ops, card, card->ctl_dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
down_read(&card->controls_rwsem);
|
||||
@ -2425,7 +2425,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
|
||||
up_read(&snd_ctl_layer_rwsem);
|
||||
up_read(&card->controls_rwsem);
|
||||
|
||||
return snd_unregister_device(&card->ctl_dev);
|
||||
return snd_unregister_device(card->ctl_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2447,7 +2447,7 @@ static int snd_ctl_dev_free(struct snd_device *device)
|
||||
xa_destroy(&card->ctl_hash);
|
||||
#endif
|
||||
up_write(&card->controls_rwsem);
|
||||
put_device(&card->ctl_dev);
|
||||
put_device(card->ctl_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2469,12 +2469,14 @@ int snd_ctl_create(struct snd_card *card)
|
||||
if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS))
|
||||
return -ENXIO;
|
||||
|
||||
snd_device_initialize(&card->ctl_dev, card);
|
||||
dev_set_name(&card->ctl_dev, "controlC%d", card->number);
|
||||
err = snd_device_alloc(&card->ctl_dev, card);
|
||||
if (err < 0)
|
||||
return err;
|
||||
dev_set_name(card->ctl_dev, "controlC%d", card->number);
|
||||
|
||||
err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
|
||||
if (err < 0)
|
||||
put_device(&card->ctl_dev);
|
||||
put_device(card->ctl_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -688,7 +688,7 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
|
||||
goto cerr;
|
||||
led->cards[card->number] = led_card;
|
||||
snprintf(link_name, sizeof(link_name), "led-%s", led->name);
|
||||
WARN(sysfs_create_link(&card->ctl_dev.kobj, &led_card->dev.kobj, link_name),
|
||||
WARN(sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj, link_name),
|
||||
"can't create symlink to controlC%i device\n", card->number);
|
||||
WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"),
|
||||
"can't create symlink to card%i\n", card->number);
|
||||
@ -714,7 +714,7 @@ static void snd_ctl_led_sysfs_remove(struct snd_card *card)
|
||||
if (!led_card)
|
||||
continue;
|
||||
snprintf(link_name, sizeof(link_name), "led-%s", led->name);
|
||||
sysfs_remove_link(&card->ctl_dev.kobj, link_name);
|
||||
sysfs_remove_link(&card->ctl_dev->kobj, link_name);
|
||||
sysfs_remove_link(&led_card->dev.kobj, "card");
|
||||
device_unregister(&led_card->dev);
|
||||
led->cards[card->number] = NULL;
|
||||
|
@ -163,7 +163,7 @@ void snd_media_stop_pipeline(struct snd_usb_substream *subs)
|
||||
|
||||
static int snd_media_mixer_init(struct snd_usb_audio *chip)
|
||||
{
|
||||
struct device *ctl_dev = &chip->card->ctl_dev;
|
||||
struct device *ctl_dev = chip->card->ctl_dev;
|
||||
struct media_intf_devnode *ctl_intf;
|
||||
struct usb_mixer_interface *mixer;
|
||||
struct media_device *mdev = chip->media_dev;
|
||||
|
Loading…
Reference in New Issue
Block a user