summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2026-09-12 18:21:42 +0200
committerTakashi Iwai <tiwai@suse.de>2026-09-13 09:07:08 +0200
commitfd95e68df6fe66344161a1329cbe5e5805e7b704 (patch)
tree195abb43428222c90401d3d348d9145609c62f59 /sound
parent76a986c980bb502c7688d605ac7a67fd257a9a1b (diff)
downloadlinux-next-fd95e68df6fe66344161a1329cbe5e5805e7b704.tar.gz
linux-next-fd95e68df6fe66344161a1329cbe5e5805e7b704.zip
ALSA: core: Fix potential UAF after asynchronous card release
Usually a sound driver releases the resources assigned to the card via snd_card_free(), and it synchronizes with the whole release procedure. However, when the card is released asynchronously via snd_card_free_when_closed() like USB-audio driver, the situation is slightly different; although the snd_card_disconnect() call at the disconnection guarantees that any newer accesses will be gated, the in-flight tasks might be still accessing to the underlying card->dev device even after the disconnection, which would cause a use-after-free in the end, as reported by fuzzers. For addressing the bug above, this patch takes the refcount of card->dev at initialization of the card object, and releases at its destructor. This assures the availability of the card->dev in its whole lifecycle. Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu> Closes: https://lore.kernel.org/CA+0ovChexj4TrZL_2iG_P0WBEbZc5+73GfB3DkciQi=R8pZOnA@mail.gmail.com Closes: https://lore.kernel.org/CA+0ovCgQUQNN=Z1tJTouiCsDaXR5M-3-SQEGk-cpPXQkM5Xh+w@mail.gmail.com Cc: <stable@vger.kernel.org> Link: https://patch.msgid.link/20260912162150.455144-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/init.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sound/core/init.c b/sound/core/init.c
index 2f7f83a7611b..d05bea3c87f5 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -310,7 +310,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
kfree(card); /* manually free here, as no destructor called */
return err;
}
- card->dev = parent;
+ card->dev = get_device(parent);
card->number = idx;
WARN_ON(IS_MODULE(CONFIG_SND) && !module);
card->module = module;
@@ -603,6 +603,7 @@ static int snd_card_do_free(struct snd_card *card)
dev_warn(card->dev, "unable to free card info\n");
/* Not fatal error */
}
+ put_device(card->dev);
if (card->release_completion)
complete(card->release_completion);
if (!managed)