[PATCH 5.19 026/207] ALSA: core: Fix double-free at snd_card_new()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Takashi Iwai <tiwai@xxxxxxx>

commit c3afa2a402d1ecefa59f88d55d9e765f52f75bd9 upstream.

During the code change to add the support for devres-managed card
instance, we put an explicit kfree(card) call at the error path in
snd_card_new().  This is needed for the early error path before the
card is initialized with the device, but is rather superfluous and
causes a double-free at the error path after the card instance is
initialized, as the destructor of the card object already contains a
kfree() call.

This patch fixes the double-free situation by removing the superfluous
kfree().  Meanwhile we need to call kfree() explicitly for the early
error path, so it's added there instead.

Fixes: e8ad415b7a55 ("ALSA: core: Add managed card creation")
Reported-by: Rondreis <linhaoguo86@xxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx>
Link: https://lore.kernel.org/r/CAB7eexL1zBnB636hwS27d-LdPYZ_R1-5fJS_h=ZbCWYU=UPWJg@xxxxxxxxxxxxxx
Link: https://lore.kernel.org/r/20220919123516.28222-1-tiwai@xxxxxxx
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
 sound/core/init.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -178,10 +178,8 @@ int snd_card_new(struct device *parent,
 		return -ENOMEM;
 
 	err = snd_card_init(card, parent, idx, xid, module, extra_size);
-	if (err < 0) {
-		kfree(card);
-		return err;
-	}
+	if (err < 0)
+		return err; /* card is freed by error handler */
 
 	*card_ret = card;
 	return 0;
@@ -231,7 +229,7 @@ int snd_devm_card_new(struct device *par
 	card->managed = true;
 	err = snd_card_init(card, parent, idx, xid, module, extra_size);
 	if (err < 0) {
-		devres_free(card);
+		devres_free(card); /* in managed mode, we need to free manually */
 		return err;
 	}
 
@@ -293,6 +291,8 @@ static int snd_card_init(struct snd_card
 		mutex_unlock(&snd_card_mutex);
 		dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
 			 idx, snd_ecards_limit - 1, err);
+		if (!card->managed)
+			kfree(card); /* manually free here, as no destructor called */
 		return err;
 	}
 	set_bit(idx, snd_cards_lock);		/* lock it */





[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux