Skip to content

Commit 930e697

Browse files
berkgokseltiwai
authored andcommitted
ALSA: usb-audio: Fix use-after-free in snd_usb_mixer_free()
When snd_usb_create_mixer() fails, snd_usb_mixer_free() frees mixer->id_elems but the controls already added to the card still reference the freed memory. Later when snd_card_register() runs, the OSS mixer layer calls their callbacks and hits a use-after-free read. Call trace: get_ctl_value+0x63f/0x820 sound/usb/mixer.c:411 get_min_max_with_quirks.isra.0+0x240/0x1f40 sound/usb/mixer.c:1241 mixer_ctl_feature_info+0x26b/0x490 sound/usb/mixer.c:1381 snd_mixer_oss_build_test+0x174/0x3a0 sound/core/oss/mixer_oss.c:887 ... snd_card_register+0x4ed/0x6d0 sound/core/init.c:923 usb_audio_probe+0x5ef/0x2a90 sound/usb/card.c:1025 Fix by calling snd_ctl_remove() for all mixer controls before freeing id_elems. We save the next pointer first because snd_ctl_remove() frees the current element. Fixes: 6639b6c ("[ALSA] usb-audio - add mixer control notifications") Cc: stable@vger.kernel.org Cc: Andrey Konovalov <andreyknvl@gmail.com> Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com> Link: https://patch.msgid.link/20260120102855.7300-1-berkcgoksel@gmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent b48fe9a commit 930e697

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

sound/usb/mixer.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2945,10 +2945,23 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
29452945

29462946
static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
29472947
{
2948+
struct usb_mixer_elem_list *list, *next;
2949+
int id;
2950+
29482951
/* kill pending URBs */
29492952
snd_usb_mixer_disconnect(mixer);
29502953

2951-
kfree(mixer->id_elems);
2954+
/* Unregister controls first, snd_ctl_remove() frees the element */
2955+
if (mixer->id_elems) {
2956+
for (id = 0; id < MAX_ID_ELEMS; id++) {
2957+
for (list = mixer->id_elems[id]; list; list = next) {
2958+
next = list->next_id_elem;
2959+
if (list->kctl)
2960+
snd_ctl_remove(mixer->chip->card, list->kctl);
2961+
}
2962+
}
2963+
kfree(mixer->id_elems);
2964+
}
29522965
if (mixer->urb) {
29532966
kfree(mixer->urb->transfer_buffer);
29542967
usb_free_urb(mixer->urb);

0 commit comments

Comments
 (0)