public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ALSA: 6fire: fix use-after-free on disconnect
@ 2026-04-10  5:13 Berk Cem Goksel
  2026-04-10  6:35 ` Takashi Iwai
  0 siblings, 1 reply; 2+ messages in thread
From: Berk Cem Goksel @ 2026-04-10  5:13 UTC (permalink / raw)
  To: Jaroslav Kysela, Takashi Iwai
  Cc: Andrey Konovalov, stable, linux-sound, linux-kernel

In usb6fire_chip_abort(), the chip struct is allocated as the card's
private data (via snd_card_new with sizeof(struct sfire_chip)).  When
snd_card_free_when_closed() is called and no file handles are open, the
card and embedded chip are freed synchronously.  The subsequent
chip->card = NULL write then hits freed slab memory.

Call trace:
  usb6fire_chip_abort sound/usb/6fire/chip.c:59 [inline]
  usb6fire_chip_disconnect+0x348/0x358 sound/usb/6fire/chip.c:182
  usb_unbind_interface+0x1a8/0x88c drivers/usb/core/driver.c:458
  ...
  hub_event+0x1a04/0x4518 drivers/usb/core/hub.c:5953

Fix by moving the card lifecycle out of usb6fire_chip_abort() and into
usb6fire_chip_disconnect().  The card pointer is saved in a local
before any teardown, snd_card_disconnect() is called first to prevent
new opens, URBs are aborted while chip is still valid, and
snd_card_free_when_closed() is called last so chip is never accessed
after the card may be freed.

Fixes: a0810c3d6dd2 ("ALSA: 6fire: Release resources at card release")
Cc: stable@vger.kernel.org
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com>
---
Patch applies to 7.0-rc6 (upstream master 5619b098e2fb).
Tested on 7.0.0-rc5 (arm64) with KASAN:

[   11.274798] BUG: KASAN: slab-use-after-free in usb6fire_chip_abort sound/usb/6fire/chip.c:59 [inline]
[   11.274798] BUG: KASAN: slab-use-after-free in usb6fire_chip_disconnect+0x348/0x358 sound/usb/6fire/chip.c:182
[   11.275503] Write of size 8 at addr ffff000013230a98 by task kworker/0:1/12
[   11.276469] CPU: 0 UID: 0 PID: 12 Comm: kworker/0:1 Not tainted 7.0.0-rc5-g663cf2b1ad64-dirty #10 PREEMPT
[   11.276485] Hardware name: linux,dummy-virt (DT)
[   11.276504] Workqueue: usb_hub_wq hub_event
[   11.276562] Call trace:
[   11.276582]  show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:499 (C)
[   11.276616]  dump_stack_lvl+0x138/0x1c8 lib/dump_stack.c:120
[   11.276666]  print_report+0x118/0x5d4 mm/kasan/report.c:482
[   11.276669]  kasan_report+0xc0/0x100 mm/kasan/report.c:595
[   11.276678]  __asan_report_store8_noabort+0x20/0x2c mm/kasan/report_generic.c:386
[   11.276684]  usb6fire_chip_abort sound/usb/6fire/chip.c:59 [inline]
[   11.276688]  usb6fire_chip_disconnect+0x348/0x358 sound/usb/6fire/chip.c:182
[   11.276692]  usb_unbind_interface+0x1a8/0x88c drivers/usb/core/driver.c:458
[   11.276697]  device_release_driver_internal+0x450/0x63c drivers/base/dd.c:1367
[   11.276699]  bus_remove_device+0x2a0/0x4f4 drivers/base/bus.c:657
[   11.276701]  device_del+0x31c/0x870 drivers/base/core.c:3880
[   11.276720]  usb_disable_device+0x2e8/0x6ec drivers/usb/core/message.c:1476
[   11.276737]  usb_disconnect+0x294/0x8d8 drivers/usb/core/hub.c:2345
[   11.276776]  hub_event+0x1a04/0x4518 drivers/usb/core/hub.c:5953
[   11.276836]  process_one_work+0x8a4/0x1dc0 kernel/workqueue.c:3276
[   11.276850]  worker_thread+0x57c/0xcac kernel/workqueue.c:3440
[   11.276888]  kthread+0x3e4/0x494 kernel/kthread.c:436
[   11.276890]  ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:860

[   11.339324] Allocated by task 12:
[   11.339765]  kasan_save_stack+0x3c/0x64 mm/kasan/common.c:57
[   11.340193]  kasan_save_track+0x20/0x3c mm/kasan/common.c:78
[   11.340615]  __kasan_kmalloc+0xb8/0xbc mm/kasan/common.c:415
[   11.341108]  snd_card_new+0x70/0x11c sound/core/init.c:184
[   11.341555]  usb6fire_chip_probe+0x298/0x864 sound/usb/6fire/chip.c:120

[   11.353835] Freed by task 12:
[   11.354171]  kasan_save_stack+0x3c/0x64 mm/kasan/common.c:57
[   11.354599]  kasan_save_track+0x20/0x3c mm/kasan/common.c:78
[   11.355023]  kasan_save_free_info+0x4c/0x78 mm/kasan/generic.c:584
[   11.355505]  __kasan_slab_free+0x5c/0x88 mm/kasan/common.c:285
[   11.355945]  kfree+0x164/0x61c mm/slub.c:6483
[   11.356285]  snd_card_do_free sound/core/init.c:597 [inline]
[   11.356778]  release_card_device+0x16c/0x1fc sound/core/init.c:153
[   11.357221]  snd_card_free_when_closed+0x30/0x44 sound/core/init.c:612
[   11.357696]  usb6fire_chip_abort sound/usb/6fire/chip.c:58 [inline]
[   11.358103]  usb6fire_chip_disconnect+0x298/0x358 sound/usb/6fire/chip.c:182

 sound/usb/6fire/chip.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index 5ff78814e687..874f6cd503ca 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -53,11 +53,6 @@ static void usb6fire_chip_abort(struct sfire_chip *chip)
 			usb6fire_comm_abort(chip);
 		if (chip->control)
 			usb6fire_control_abort(chip);
-		if (chip->card) {
-			snd_card_disconnect(chip->card);
-			snd_card_free_when_closed(chip->card);
-			chip->card = NULL;
-		}
 	}
 }
 
@@ -168,6 +163,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
 static void usb6fire_chip_disconnect(struct usb_interface *intf)
 {
 	struct sfire_chip *chip;
+	struct snd_card *card;
 
 	chip = usb_get_intfdata(intf);
 	if (chip) { /* if !chip, fw upload has been performed */
@@ -178,8 +174,19 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
 				chips[chip->regidx] = NULL;
 			}
 
+			/*
+			 * Save card pointer before teardown.
+			 * snd_card_free_when_closed() may free card (and
+			 * the embedded chip) immediately, so it must be
+			 * called last and chip must not be accessed after.
+			 */
+			card = chip->card;
 			chip->shutdown = true;
+			if (card)
+				snd_card_disconnect(card);
 			usb6fire_chip_abort(chip);
+			if (card)
+				snd_card_free_when_closed(card);
 		}
 	}
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] ALSA: 6fire: fix use-after-free on disconnect
  2026-04-10  5:13 [PATCH] ALSA: 6fire: fix use-after-free on disconnect Berk Cem Goksel
@ 2026-04-10  6:35 ` Takashi Iwai
  0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2026-04-10  6:35 UTC (permalink / raw)
  To: Berk Cem Goksel
  Cc: Jaroslav Kysela, Takashi Iwai, Andrey Konovalov, stable,
	linux-sound, linux-kernel

On Fri, 10 Apr 2026 07:13:41 +0200,
Berk Cem Goksel wrote:
> 
> In usb6fire_chip_abort(), the chip struct is allocated as the card's
> private data (via snd_card_new with sizeof(struct sfire_chip)).  When
> snd_card_free_when_closed() is called and no file handles are open, the
> card and embedded chip are freed synchronously.  The subsequent
> chip->card = NULL write then hits freed slab memory.
> 
> Call trace:
>   usb6fire_chip_abort sound/usb/6fire/chip.c:59 [inline]
>   usb6fire_chip_disconnect+0x348/0x358 sound/usb/6fire/chip.c:182
>   usb_unbind_interface+0x1a8/0x88c drivers/usb/core/driver.c:458
>   ...
>   hub_event+0x1a04/0x4518 drivers/usb/core/hub.c:5953
> 
> Fix by moving the card lifecycle out of usb6fire_chip_abort() and into
> usb6fire_chip_disconnect().  The card pointer is saved in a local
> before any teardown, snd_card_disconnect() is called first to prevent
> new opens, URBs are aborted while chip is still valid, and
> snd_card_free_when_closed() is called last so chip is never accessed
> after the card may be freed.
> 
> Fixes: a0810c3d6dd2 ("ALSA: 6fire: Release resources at card release")
> Cc: stable@vger.kernel.org
> Cc: Andrey Konovalov <andreyknvl@gmail.com>
> Signed-off-by: Berk Cem Goksel <berkcgoksel@gmail.com>

Applied now.  Thanks.


Takashi

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-04-10  6:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-10  5:13 [PATCH] ALSA: 6fire: fix use-after-free on disconnect Berk Cem Goksel
2026-04-10  6:35 ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox