ALSA: core: Fix double-free at snd_card_new()
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: e8ad415b7a
("ALSA: core: Add managed card creation")
Reported-by: Rondreis <linhaoguo86@gmail.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/CAB7eexL1zBnB636hwS27d-LdPYZ_R1-5fJS_h=ZbCWYU=UPWJg@mail.gmail.com
Link: https://lore.kernel.org/r/20220919123516.28222-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
496322302b
commit
c3afa2a402
|
@ -178,10 +178,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
err = snd_card_init(card, parent, idx, xid, module, extra_size);
|
err = snd_card_init(card, parent, idx, xid, module, extra_size);
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
kfree(card);
|
return err; /* card is freed by error handler */
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
*card_ret = card;
|
*card_ret = card;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -233,7 +231,7 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
|
||||||
card->managed = true;
|
card->managed = true;
|
||||||
err = snd_card_init(card, parent, idx, xid, module, extra_size);
|
err = snd_card_init(card, parent, idx, xid, module, extra_size);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
devres_free(card);
|
devres_free(card); /* in managed mode, we need to free manually */
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,6 +295,8 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
|
||||||
mutex_unlock(&snd_card_mutex);
|
mutex_unlock(&snd_card_mutex);
|
||||||
dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
|
dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
|
||||||
idx, snd_ecards_limit - 1, err);
|
idx, snd_ecards_limit - 1, err);
|
||||||
|
if (!card->managed)
|
||||||
|
kfree(card); /* manually free here, as no destructor called */
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
set_bit(idx, snd_cards_lock); /* lock it */
|
set_bit(idx, snd_cards_lock); /* lock it */
|
||||||
|
|
Loading…
Reference in New Issue