ALSA: usb-audio: Fix double-free in error paths after snd_usb_add_audio_stream()...
[pandora-kernel.git] / sound / usb / stream.c
index 33a335b..7dce074 100644 (file)
@@ -77,7 +77,9 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
 /*
  * add this endpoint to the chip instance.
  * if a stream with the same endpoint already exists, append to it.
 /*
  * add this endpoint to the chip instance.
  * if a stream with the same endpoint already exists, append to it.
- * if not, create a new pcm stream.
+ * if not, create a new pcm stream. note, fp is added to the substream
+ * fmt_list and will be freed on the chip instance release. do not free
+ * fp or do remove it from the substream fmt_list to avoid double-free.
  */
 int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
                             int stream,
  */
 int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
                             int stream,
@@ -403,6 +405,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                                        * (fp->maxpacksize & 0x7ff);
                fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
                fp->clock = clock;
                                        * (fp->maxpacksize & 0x7ff);
                fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
                fp->clock = clock;
+               INIT_LIST_HEAD(&fp->list);
 
                /* some quirks for attributes here */
 
 
                /* some quirks for attributes here */
 
@@ -446,6 +449,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
                snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
                err = snd_usb_add_audio_stream(chip, stream, fp);
                if (err < 0) {
                snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
                err = snd_usb_add_audio_stream(chip, stream, fp);
                if (err < 0) {
+                       list_del(&fp->list); /* unlink for avoiding double-free */
                        kfree(fp->rate_table);
                        kfree(fp);
                        return err;
                        kfree(fp->rate_table);
                        kfree(fp);
                        return err;