Commit dbd9d1cbf970 for kernel

commit dbd9d1cbf9700528c8595ab1fa7ef832e79821fe
Author: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com>
Date:   Tue Sep 15 23:31:10 2026 +0700

    ALSA: usb-audio: fix list_add double-add in push_back_to_ready_list

    stop_urbs() clears ep->ready_playback_urbs with a bare INIT_LIST_HEAD()
    instead of unlinking each queued snd_urb_ctx. If a URB survives past
    wait_clear_urbs()'s forced STOPPING->STOPPED timeout, its ctx is left
    looking "linked" (stale next/prev) even though the list head has
    forgotten it. When the endpoint later restarts and re-queues that same
    ctx onto the (now real) ready list, and the old URB's completion
    handler then calls push_back_to_ready_list() for it a second time, the
    ctx is still the list's own tail and list_add's double-add check trips:

      kernel BUG at lib/list_debug.c:35 (list_add double add)

    Guard push_back_to_ready_list() with a list_empty() check so a
    still-linked ctx isn't re-added, and make stop_urbs() actually unlink
    each ctx via list_del_init() instead of only resetting the head, so a
    dropped ctx doesn't keep looking linked to that guard.

    Reported-by: syzbot+9fe3b8d9f5c64ff410a7@syzkaller.appspotmail.com
    Closes: https://syzkaller.appspot.com/bug?extid=9fe3b8d9f5c64ff410a7
    Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com>
    Link: https://patch.msgid.link/20260915163110.58124-1-ngocthang2710.1999@gmail.com
    Signed-off-by: Takashi Iwai <tiwai@suse.de>

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index b72ce1e9bfb1..879d0451536e 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -449,7 +449,9 @@ static void push_back_to_ready_list(struct snd_usb_endpoint *ep,
 				    struct snd_urb_ctx *ctx)
 {
 	guard(spinlock_irqsave)(&ep->lock);
-	list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
+	/* ctx may still be linked: a stale completion racing a stop/restart. */
+	if (list_empty(&ctx->ready_list))
+		list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
 }

 /*
@@ -1037,6 +1039,7 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
  */
 static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending)
 {
+	struct snd_urb_ctx *ctx, *n;
 	unsigned int i;

 	if (!force && atomic_read(&ep->running))
@@ -1046,7 +1049,9 @@ static int stop_urbs(struct snd_usb_endpoint *ep, bool force, bool keep_pending)
 		return 0;

 	scoped_guard(spinlock_irqsave, &ep->lock) {
-		INIT_LIST_HEAD(&ep->ready_playback_urbs);
+		/* Unlink each ctx; INIT_LIST_HEAD() alone would leave them looking linked. */
+		list_for_each_entry_safe(ctx, n, &ep->ready_playback_urbs, ready_list)
+			list_del_init(&ctx->ready_list);
 		ep->next_packet_head = 0;
 		ep->next_packet_queued = 0;
 	}