* [PATCH 0/2] ALSA: caiaq: fix UAF, double-free, and USB refcount bugs @ 2026-04-10 4:59 Berk Cem Goksel 2026-04-10 4:59 ` [PATCH 1/2] ALSA: caiaq: fix use-after-free and double-free in setup_card() Berk Cem Goksel 2026-04-10 4:59 ` [PATCH 2/2] ALSA: caiaq: take a reference on the USB device in create_card() Berk Cem Goksel 0 siblings, 2 replies; 5+ messages in thread From: Berk Cem Goksel @ 2026-04-10 4:59 UTC (permalink / raw) To: Takashi Iwai, Jaroslav Kysela Cc: linux-sound, linux-kernel, Andrey Konovalov, Berk Cem Goksel This series fixes two bugs in the caiaq USB sound driver, both reachable via a malformed or malicious USB device using raw-gadget + dummy_hcd. Patch 1 adds a missing return after snd_card_free() in setup_card() when snd_card_register() fails. Without it, execution falls through to snd_usb_caiaq_control_init() on a freed card (use-after-free), and the caller then leaves the freed pointer in usb_set_intfdata(), producing a double-free on disconnect. Patch 2 takes a proper reference on the parent USB device in create_card() with usb_get_dev() and drops it with usb_put_dev() in the private_free callback. It also removes a usb_reset_device() call from that callback, which was both racing against an already-freed usb_device and inappropriate in a teardown path. A related stack out-of-bounds read in init_card() was sent separately and has already been applied; this series is the remainder of that investigation. Tested on 7.0.0-rc5 arm64 with KASAN and lockdep enabled. Reproducers require CONFIG_USB_RAW_GADGET and CONFIG_USB_DUMMY_HCD and are available on request. Berk Cem Goksel (2): ALSA: caiaq: fix use-after-free and double-free in setup_card() ALSA: caiaq: take a reference on the USB device in create_card() sound/usb/caiaq/device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] ALSA: caiaq: fix use-after-free and double-free in setup_card() 2026-04-10 4:59 [PATCH 0/2] ALSA: caiaq: fix UAF, double-free, and USB refcount bugs Berk Cem Goksel @ 2026-04-10 4:59 ` Berk Cem Goksel 2026-04-10 6:26 ` Takashi Iwai 2026-04-10 4:59 ` [PATCH 2/2] ALSA: caiaq: take a reference on the USB device in create_card() Berk Cem Goksel 1 sibling, 1 reply; 5+ messages in thread From: Berk Cem Goksel @ 2026-04-10 4:59 UTC (permalink / raw) To: Takashi Iwai, Jaroslav Kysela Cc: linux-sound, linux-kernel, Andrey Konovalov, Berk Cem Goksel, stable When snd_card_register() fails in setup_card(), snd_card_free() is called on the card, but there is no return statement afterwards. Execution falls through to snd_usb_caiaq_control_init(cdev), which dereferences members of the just-freed card, resulting in a use-after-free. setup_card() is void and init_card() still returns 0 on this path, so snd_probe() leaves the freed card pointer in the USB interface's private data via usb_set_intfdata(). When the device is later disconnected, snd_usb_caiaq_disconnect() calls snd_card_free_when_closed() on that same pointer, producing a double-free and slab corruption. Add the missing return so a failed snd_card_register() cleanly aborts setup without touching freed memory. The issue is reachable by any caiaq-compatible USB device whose descriptors cause snd_card_register() to fail. It was reproduced with raw-gadget + dummy_hcd on 7.0.0-rc5 (arm64, KASAN). Fixes: 523f1dce7096 ("ALSA: snd-usb-caiaq: add support for NI Audio Kontrol 1") Cc: stable@vger.kernel.org Cc: Andrey Konovalov <andreyknvl@gmail.com> Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com> --- sound/usb/caiaq/device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -369,6 +369,7 @@ if (ret < 0) { dev_err(dev, "snd_card_register() returned %d\n", ret); snd_card_free(cdev->chip.card); + return; } ret = snd_usb_caiaq_control_init(cdev); ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] ALSA: caiaq: fix use-after-free and double-free in setup_card() 2026-04-10 4:59 ` [PATCH 1/2] ALSA: caiaq: fix use-after-free and double-free in setup_card() Berk Cem Goksel @ 2026-04-10 6:26 ` Takashi Iwai 0 siblings, 0 replies; 5+ messages in thread From: Takashi Iwai @ 2026-04-10 6:26 UTC (permalink / raw) To: Berk Cem Goksel Cc: Takashi Iwai, Jaroslav Kysela, linux-sound, linux-kernel, Andrey Konovalov, stable On Fri, 10 Apr 2026 06:59:03 +0200, Berk Cem Goksel wrote: > > When snd_card_register() fails in setup_card(), snd_card_free() is > called on the card, but there is no return statement afterwards. > Execution falls through to snd_usb_caiaq_control_init(cdev), which > dereferences members of the just-freed card, resulting in a > use-after-free. > > setup_card() is void and init_card() still returns 0 on this path, > so snd_probe() leaves the freed card pointer in the USB interface's > private data via usb_set_intfdata(). When the device is later > disconnected, snd_usb_caiaq_disconnect() calls > snd_card_free_when_closed() on that same pointer, producing a > double-free and slab corruption. > > Add the missing return so a failed snd_card_register() cleanly > aborts setup without touching freed memory. > > The issue is reachable by any caiaq-compatible USB device whose > descriptors cause snd_card_register() to fail. It was reproduced > with raw-gadget + dummy_hcd on 7.0.0-rc5 (arm64, KASAN). > > Fixes: 523f1dce7096 ("ALSA: snd-usb-caiaq: add support for NI Audio Kontrol 1") > Cc: stable@vger.kernel.org > Cc: Andrey Konovalov <andreyknvl@gmail.com> > Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com> The code fix itself looks fine, but the Fixes tag above points to a non-existing commit. What tree are you using? thanks, Takashi > --- > sound/usb/caiaq/device.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c > --- a/sound/usb/caiaq/device.c > +++ b/sound/usb/caiaq/device.c > @@ -369,6 +369,7 @@ > if (ret < 0) { > dev_err(dev, "snd_card_register() returned %d\n", ret); > snd_card_free(cdev->chip.card); > + return; > } > > ret = snd_usb_caiaq_control_init(cdev); ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] ALSA: caiaq: take a reference on the USB device in create_card() 2026-04-10 4:59 [PATCH 0/2] ALSA: caiaq: fix UAF, double-free, and USB refcount bugs Berk Cem Goksel 2026-04-10 4:59 ` [PATCH 1/2] ALSA: caiaq: fix use-after-free and double-free in setup_card() Berk Cem Goksel @ 2026-04-10 4:59 ` Berk Cem Goksel 2026-04-10 6:31 ` Takashi Iwai 1 sibling, 1 reply; 5+ messages in thread From: Berk Cem Goksel @ 2026-04-10 4:59 UTC (permalink / raw) To: Takashi Iwai, Jaroslav Kysela Cc: linux-sound, linux-kernel, Andrey Konovalov, Berk Cem Goksel, stable The caiaq driver stores a pointer to the parent USB device in cdev->chip.dev but never takes a reference on it. The card's private_free callback, snd_usb_caiaq_card_free(), can run asynchronously via snd_card_free_when_closed() after the USB device has already been disconnected and freed, so any access to cdev->chip.dev in that path dereferences a freed usb_device. On top of the refcounting issue, the current card_free implementation calls usb_reset_device(cdev->chip.dev). A reset in a free callback is inappropriate: the device is going away, the call takes the device lock in a teardown context, and the reset races with the disconnect path that the callback is already cleaning up after. Take a reference on the USB device in create_card() with usb_get_dev(), drop it with usb_put_dev() in the free callback, and remove the usb_reset_device() call. Fixes: 523f1dce7096 ("ALSA: snd-usb-caiaq: add support for NI Audio Kontrol 1") Cc: stable@vger.kernel.org Cc: Andrey Konovalov <andreyknvl@gmail.com> Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com> --- sound/usb/caiaq/device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -385,7 +385,8 @@ snd_usb_caiaq_input_free(cdev); #endif snd_usb_caiaq_audio_free(cdev); - usb_reset_device(cdev->chip.dev); + if (cdev->chip.dev) + usb_put_dev(cdev->chip.dev); } static int create_card(struct usb_device *usb_dev, @@ -411,7 +412,7 @@ return err; cdev = caiaqdev(card); - cdev->chip.dev = usb_dev; + cdev->chip.dev = usb_get_dev(usb_dev); cdev->chip.card = card; cdev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor), le16_to_cpu(usb_dev->descriptor.idProduct)); ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] ALSA: caiaq: take a reference on the USB device in create_card() 2026-04-10 4:59 ` [PATCH 2/2] ALSA: caiaq: take a reference on the USB device in create_card() Berk Cem Goksel @ 2026-04-10 6:31 ` Takashi Iwai 0 siblings, 0 replies; 5+ messages in thread From: Takashi Iwai @ 2026-04-10 6:31 UTC (permalink / raw) To: Berk Cem Goksel Cc: Takashi Iwai, Jaroslav Kysela, linux-sound, linux-kernel, Andrey Konovalov, stable On Fri, 10 Apr 2026 06:59:04 +0200, Berk Cem Goksel wrote: > > The caiaq driver stores a pointer to the parent USB device in > cdev->chip.dev but never takes a reference on it. The card's > private_free callback, snd_usb_caiaq_card_free(), can run > asynchronously via snd_card_free_when_closed() after the USB > device has already been disconnected and freed, so any access to > cdev->chip.dev in that path dereferences a freed usb_device. > > On top of the refcounting issue, the current card_free implementation > calls usb_reset_device(cdev->chip.dev). A reset in a free callback > is inappropriate: the device is going away, the call takes the > device lock in a teardown context, and the reset races with the > disconnect path that the callback is already cleaning up after. > > Take a reference on the USB device in create_card() with > usb_get_dev(), drop it with usb_put_dev() in the free callback, > and remove the usb_reset_device() call. > > Fixes: 523f1dce7096 ("ALSA: snd-usb-caiaq: add support for NI Audio Kontrol 1") > Cc: stable@vger.kernel.org > Cc: Andrey Konovalov <andreyknvl@gmail.com> > Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com> > --- > sound/usb/caiaq/device.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c > --- a/sound/usb/caiaq/device.c > +++ b/sound/usb/caiaq/device.c > @@ -385,7 +385,8 @@ > snd_usb_caiaq_input_free(cdev); > #endif > snd_usb_caiaq_audio_free(cdev); > - usb_reset_device(cdev->chip.dev); > + if (cdev->chip.dev) > + usb_put_dev(cdev->chip.dev); usb_put_dev() itself has a NULL check, so you can pass as is, too. And, the Fixes tag is incorrect in this patch, too. thanks, Takashi > } > > static int create_card(struct usb_device *usb_dev, > @@ -411,7 +412,7 @@ > return err; > > cdev = caiaqdev(card); > - cdev->chip.dev = usb_dev; > + cdev->chip.dev = usb_get_dev(usb_dev); > cdev->chip.card = card; > cdev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor), > le16_to_cpu(usb_dev->descriptor.idProduct)); ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-10 6:31 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-10 4:59 [PATCH 0/2] ALSA: caiaq: fix UAF, double-free, and USB refcount bugs Berk Cem Goksel 2026-04-10 4:59 ` [PATCH 1/2] ALSA: caiaq: fix use-after-free and double-free in setup_card() Berk Cem Goksel 2026-04-10 6:26 ` Takashi Iwai 2026-04-10 4:59 ` [PATCH 2/2] ALSA: caiaq: take a reference on the USB device in create_card() Berk Cem Goksel 2026-04-10 6:31 ` Takashi Iwai
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox