| From fa63a268382db878f5701bd39451e0459fdff716 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 16 Dec 2025 15:06:24 +0100 |
| Subject: ALSA: control: Relax __free() variable declarations |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| [ Upstream commit 7b4721ca3159bce6338dbdf9188b785083571ed4 ] |
| |
| We used to have a variable declaration with __free() initialized with |
| NULL. This was to keep the old coding style rule, but recently it's |
| relaxed and rather recommends to follow the new rule to declare in |
| place of use for __free() -- which avoids potential deadlocks or UAFs |
| with nested cleanups. |
| |
| Although the current code has no bug, per se, let's follow the new |
| standard and move the declaration to the place of assignment (or |
| directly assign the allocated result) instead of NULL initializations. |
| |
| Fixes: 7dba48a474e6 ("ALSA: control_led: Use guard() for locking") |
| Fixes: 1052d9882269 ("ALSA: control: Use automatic cleanup of kfree()") |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Link: https://patch.msgid.link/20251216140634.171890-3-tiwai@suse.de |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| sound/core/control.c | 12 ++++++------ |
| sound/core/control_compat.c | 21 +++++++++++---------- |
| sound/core/control_led.c | 12 ++++++------ |
| 3 files changed, 23 insertions(+), 22 deletions(-) |
| |
| diff --git a/sound/core/control.c b/sound/core/control.c |
| index 9c3fd5113a617..486d1bc4dac27 100644 |
| --- a/sound/core/control.c |
| +++ b/sound/core/control.c |
| @@ -867,9 +867,9 @@ EXPORT_SYMBOL(snd_ctl_find_id); |
| static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, |
| unsigned int cmd, void __user *arg) |
| { |
| - struct snd_ctl_card_info *info __free(kfree) = NULL; |
| + struct snd_ctl_card_info *info __free(kfree) = |
| + kzalloc(sizeof(*info), GFP_KERNEL); |
| |
| - info = kzalloc(sizeof(*info), GFP_KERNEL); |
| if (! info) |
| return -ENOMEM; |
| scoped_guard(rwsem_read, &snd_ioctl_rwsem) { |
| @@ -1244,10 +1244,10 @@ static int snd_ctl_elem_read(struct snd_card *card, |
| static int snd_ctl_elem_read_user(struct snd_card *card, |
| struct snd_ctl_elem_value __user *_control) |
| { |
| - struct snd_ctl_elem_value *control __free(kfree) = NULL; |
| int result; |
| + struct snd_ctl_elem_value *control __free(kfree) = |
| + memdup_user(_control, sizeof(*control)); |
| |
| - control = memdup_user(_control, sizeof(*control)); |
| if (IS_ERR(control)) |
| return PTR_ERR(control); |
| |
| @@ -1320,11 +1320,11 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, |
| static int snd_ctl_elem_write_user(struct snd_ctl_file *file, |
| struct snd_ctl_elem_value __user *_control) |
| { |
| - struct snd_ctl_elem_value *control __free(kfree) = NULL; |
| struct snd_card *card; |
| int result; |
| + struct snd_ctl_elem_value *control __free(kfree) = |
| + memdup_user(_control, sizeof(*control)); |
| |
| - control = memdup_user(_control, sizeof(*control)); |
| if (IS_ERR(control)) |
| return PTR_ERR(control); |
| |
| diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c |
| index 6459809ed3648..b8988a4bcd9b5 100644 |
| --- a/sound/core/control_compat.c |
| +++ b/sound/core/control_compat.c |
| @@ -80,10 +80,10 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, |
| struct snd_ctl_elem_info32 __user *data32) |
| { |
| struct snd_card *card = ctl->card; |
| - struct snd_ctl_elem_info *data __free(kfree) = NULL; |
| int err; |
| + struct snd_ctl_elem_info *data __free(kfree) = |
| + kzalloc(sizeof(*data), GFP_KERNEL); |
| |
| - data = kzalloc(sizeof(*data), GFP_KERNEL); |
| if (! data) |
| return -ENOMEM; |
| |
| @@ -169,14 +169,15 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, |
| int *countp) |
| { |
| struct snd_kcontrol *kctl; |
| - struct snd_ctl_elem_info *info __free(kfree) = NULL; |
| int err; |
| |
| guard(rwsem_read)(&card->controls_rwsem); |
| kctl = snd_ctl_find_id(card, id); |
| if (!kctl) |
| return -ENOENT; |
| - info = kzalloc(sizeof(*info), GFP_KERNEL); |
| + |
| + struct snd_ctl_elem_info *info __free(kfree) = |
| + kzalloc(sizeof(*info), GFP_KERNEL); |
| if (info == NULL) |
| return -ENOMEM; |
| info->id = *id; |
| @@ -280,10 +281,10 @@ static int copy_ctl_value_to_user(void __user *userdata, |
| static int __ctl_elem_read_user(struct snd_card *card, |
| void __user *userdata, void __user *valuep) |
| { |
| - struct snd_ctl_elem_value *data __free(kfree) = NULL; |
| int err, type, count; |
| + struct snd_ctl_elem_value *data __free(kfree) = |
| + kzalloc(sizeof(*data), GFP_KERNEL); |
| |
| - data = kzalloc(sizeof(*data), GFP_KERNEL); |
| if (data == NULL) |
| return -ENOMEM; |
| |
| @@ -314,11 +315,11 @@ static int ctl_elem_read_user(struct snd_card *card, |
| static int __ctl_elem_write_user(struct snd_ctl_file *file, |
| void __user *userdata, void __user *valuep) |
| { |
| - struct snd_ctl_elem_value *data __free(kfree) = NULL; |
| struct snd_card *card = file->card; |
| int err, type, count; |
| + struct snd_ctl_elem_value *data __free(kfree) = |
| + kzalloc(sizeof(*data), GFP_KERNEL); |
| |
| - data = kzalloc(sizeof(*data), GFP_KERNEL); |
| if (data == NULL) |
| return -ENOMEM; |
| |
| @@ -378,9 +379,9 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, |
| struct snd_ctl_elem_info32 __user *data32, |
| int replace) |
| { |
| - struct snd_ctl_elem_info *data __free(kfree) = NULL; |
| + struct snd_ctl_elem_info *data __free(kfree) = |
| + kzalloc(sizeof(*data), GFP_KERNEL); |
| |
| - data = kzalloc(sizeof(*data), GFP_KERNEL); |
| if (! data) |
| return -ENOMEM; |
| |
| diff --git a/sound/core/control_led.c b/sound/core/control_led.c |
| index e33dfcf863cf1..c7641d5084e7d 100644 |
| --- a/sound/core/control_led.c |
| +++ b/sound/core/control_led.c |
| @@ -245,12 +245,12 @@ DEFINE_FREE(snd_card_unref, struct snd_card *, if (_T) snd_card_unref(_T)) |
| static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id, |
| unsigned int group, bool set) |
| { |
| - struct snd_card *card __free(snd_card_unref) = NULL; |
| struct snd_kcontrol *kctl; |
| struct snd_kcontrol_volatile *vd; |
| unsigned int ioff, access, new_access; |
| + struct snd_card *card __free(snd_card_unref) = |
| + snd_card_ref(card_number); |
| |
| - card = snd_card_ref(card_number); |
| if (!card) |
| return -ENXIO; |
| guard(rwsem_write)(&card->controls_rwsem); |
| @@ -302,13 +302,13 @@ static void snd_ctl_led_clean(struct snd_card *card) |
| |
| static int snd_ctl_led_reset(int card_number, unsigned int group) |
| { |
| - struct snd_card *card __free(snd_card_unref) = NULL; |
| struct snd_ctl_led_ctl *lctl, *_lctl; |
| struct snd_ctl_led *led; |
| struct snd_kcontrol_volatile *vd; |
| bool change = false; |
| + struct snd_card *card __free(snd_card_unref) = |
| + snd_card_ref(card_number); |
| |
| - card = snd_card_ref(card_number); |
| if (!card) |
| return -ENXIO; |
| |
| @@ -598,11 +598,11 @@ static ssize_t list_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); |
| - struct snd_card *card __free(snd_card_unref) = NULL; |
| struct snd_ctl_led_ctl *lctl; |
| size_t l = 0; |
| + struct snd_card *card __free(snd_card_unref) = |
| + snd_card_ref(led_card->number); |
| |
| - card = snd_card_ref(led_card->number); |
| if (!card) |
| return -ENXIO; |
| guard(rwsem_read)(&card->controls_rwsem); |
| -- |
| 2.51.0 |
| |