]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ALSA: 6fire: Release resources at card release
authorTakashi Iwai <tiwai@suse.de>
Wed, 13 Nov 2024 11:10:39 +0000 (12:10 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 13 Nov 2024 12:33:47 +0000 (13:33 +0100)
The current 6fire code tries to release the resources right after the
call of usb6fire_chip_abort().  But at this moment, the card object
might be still in use (as we're calling snd_card_free_when_closed()).

For avoid potential UAFs, move the release of resources to the card's
private_free instead of the manual call of usb6fire_chip_destroy() at
the USB disconnect callback.

Fixes: c6d43ba816d1 ("ALSA: usb/6fire - Driver for TerraTec DMX 6Fire USB")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20241113111042.15058-6-tiwai@suse.de
sound/usb/6fire/chip.c

index 33e962178c9363aa4f36d40c1258e9d5dd643c9d..d562a30b087f0107a640285c30b1998570b62ef6 100644 (file)
@@ -61,8 +61,10 @@ static void usb6fire_chip_abort(struct sfire_chip *chip)
        }
 }
 
-static void usb6fire_chip_destroy(struct sfire_chip *chip)
+static void usb6fire_card_free(struct snd_card *card)
 {
+       struct sfire_chip *chip = card->private_data;
+
        if (chip) {
                if (chip->pcm)
                        usb6fire_pcm_destroy(chip);
@@ -72,8 +74,6 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip)
                        usb6fire_comm_destroy(chip);
                if (chip->control)
                        usb6fire_control_destroy(chip);
-               if (chip->card)
-                       snd_card_free(chip->card);
        }
 }
 
@@ -136,6 +136,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
        chip->regidx = regidx;
        chip->intf_count = 1;
        chip->card = card;
+       card->private_free = usb6fire_card_free;
 
        ret = usb6fire_comm_init(chip);
        if (ret < 0)
@@ -162,7 +163,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
        return 0;
 
 destroy_chip:
-       usb6fire_chip_destroy(chip);
+       snd_card_free(card);
        return ret;
 }
 
@@ -181,7 +182,6 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
 
                        chip->shutdown = true;
                        usb6fire_chip_abort(chip);
-                       usb6fire_chip_destroy(chip);
                }
        }
 }