From 344e74ac50aff89674a1bea153f008bfb31ed952 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Oct 2026 19:25:24 +0200 Subject: [PATCH] ALSA: core: Fix leaks at snd_card_init() error paths When the snd_card object is initialized internally in snd_card_init(), the error path of card->value_buf allocation returns straightly as an error without invoking the destructor, which would leak resources. Also, the other error paths in snd_card_init() release the card object only via put_device(), and this misses the cleanups that are done in snd_card_disconnect(); namely, the reserved slot bit in snd_cards_lock is never cleared, so the card index remains occupied, and the debugfs directory created for the card is left over. Fix them by calling snd_card_free() at the error path, which performs both the disconnection and the release properly. As snd_card_free() calls snd_device_free_all() internally, the explicit call is dropped, and the error labels are unified. Fixes: 84446536f63d ("ALSA: control: Verify put() result when in debug mode") Reported-by: Sashiko Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20261007172533.14667-7-tiwai@suse.de --- sound/core/init.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/core/init.c b/sound/core/init.c index dbe2acfa59fe..9deb5e920d0d 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -334,7 +334,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent, err = snd_info_card_create(card); if (err < 0) { dev_err(parent, "unable to create card info\n"); - goto __error_ctl; + goto __error; } #ifdef CONFIG_SND_DEBUG @@ -343,16 +343,16 @@ static int snd_card_init(struct snd_card *card, struct device *parent, #endif #ifdef CONFIG_SND_CTL_DEBUG card->value_buf = kmalloc_obj(*card->value_buf); - if (!card->value_buf) - return -ENOMEM; + if (!card->value_buf) { + err = -ENOMEM; + goto __error; + } #endif return 0; - __error_ctl: - snd_device_free_all(card); __error: - put_device(&card->card_dev); - return err; + snd_card_free(card); + return err; } /**