All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Sergei Nizovtsev <snizovtsev@cloudlinux.com>
Cc: Takashi Iwai <tiwai@suse.com>, Jaroslav Kysela <perex@perex.cz>,
	Daniel Mack <zonque@gmail.com>,
	linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
Subject: Re: [PATCH] ALSA: caiaq: Kill EP1 URB before unregistering the input device
Date: Thu, 12 Nov 2026 13:36:37 +0100	[thread overview]
Message-ID: <87mrrerzu2.wl-tiwai@suse.de> (raw)
In-Reply-To: <20261112094904.2430318-1-snizovtsev@cloudlinux.com>

On Thu, 12 Nov 2026 10:48:54 +0100,
Sergei Nizovtsev wrote:
> 
> snd_disconnect() unregisters the input device via
> snd_usb_caiaq_input_disconnect() and only afterwards kills the EP1
> command URB (cdev->ep1_in_urb). The EP1 completion handler
> usb_ep1_command_reply_dispatch() feeds snd_usb_caiaq_input_dispatch()
> for EP1_CMD_READ_{ERP,ANALOG,IO} replies, which report into
> cdev->input_dev. Since commit b04dcbb7f7b1 ("ALSA: caiaq: Use
> snd_card_free_when_closed() at disconnection") the input device is
> unregistered from snd_usb_caiaq_input_disconnect() but cdev->input_dev
> is cleared only later, in snd_usb_caiaq_input_free() from the card
> destructor. As the dispatch guard only tests cdev->input_dev for NULL,
> an EP1 reply that completes after input_unregister_device() but before
> cdev->ep1_in_urb is killed reports into an input device that has
> already been unregistered and, with no evdev client holding it open,
> freed.
> 
> Normally the window is closed by the USB core: usb_unbind_interface()
> calls usb_disable_interface() before ->disconnect(), which flushes the
> EP1 URB as long as endpoint 0x81 belongs to the interface being
> unbound. But caiaq addresses EP1 through the device-wide pipe
> usb_rcvbulkpipe(usb_dev, 0x1) without checking which interface owns
> the endpoint. If a device declares it in another interface, the URB
> stays live across snd_disconnect() of the interface that owns the card.
> 
> This needs a crafted device descriptor; a device that has EP1 in the
> interface caiaq is bound to is not affected.
> 
> Kill cdev->ep1_in_urb (and the paired midi_out_urb) before the input
> and audio disconnect helpers, so no EP1 completion can run once the
> input device has been unregistered.
> 
> Reproduced under KASAN with raw-gadget + dummy_hcd emulating an Audio
> Kontrol 1 (17cc:0815) with the EP1 bulk pair in interface 1: only
> interface 0 was bound to snd-usb-caiaq and then unbound through sysfs
> while the gadget flooded EP1 with EP1_CMD_READ_ERP replies. With no PCM
> stream running the window is very short and was only hit by stalling
> the unbinding CPU with a kgdb breakpoint at
> snd_usb_caiaq_audio_disconnect(). With the fix applied, the same test
> runs clean.
> 
>   BUG: KASAN: slab-use-after-free in input_event+0x3a/0xc0
>   Read of size 8 at addr ffff8880151a4028 by task sh/118
> 
>   Call Trace:
>    <IRQ>
>    input_event+0x3a/0xc0
>    snd_usb_caiaq_input_dispatch+0xab2/0xf00
>    usb_ep1_command_reply_dispatch+0x1f3/0x580
>    __usb_hcd_giveback_urb+0x246/0x400
>    dummy_timer+0x1415/0x3380
>    __hrtimer_run_queues+0x39d/0x800
>    hrtimer_run_softirq+0x187/0x2d0
>    handle_softirqs+0x1ff/0x930
>    __irq_exit_rcu+0x15b/0x210
>    irq_exit_rcu+0xe/0x20
>    sysvec_apic_timer_interrupt+0x81/0xb0
>    </IRQ>
>    <TASK>
>    asm_sysvec_apic_timer_interrupt+0x1a/0x20
>   RIP: 0010:snd_usb_caiaq_audio_disconnect+0x0/0x70
>    snd_disconnect+0x81/0x110
>    usb_unbind_interface+0x1a0/0x860
>    device_release_driver_internal+0x2c5/0x470
>    unbind_store+0xde/0x100
>    </TASK>
> 
>   Allocated by task 80:
>    input_allocate_device+0x47/0x340
>    snd_usb_caiaq_input_init+0x4c/0x1ac0
>    snd_probe+0xab3/0x1160
>    usb_probe_interface+0x2ea/0x810
> 
>   Freed by task 118:
>    kfree+0x1ea/0x5c0
>    input_dev_release+0xab/0xd0
>    device_release+0xcf/0x250
>    kobject_put+0x169/0x320
>    snd_disconnect+0x79/0x110
>    usb_unbind_interface+0x1a0/0x860
> 
> Fixes: b04dcbb7f7b1 ("ALSA: caiaq: Use snd_card_free_when_closed() at disconnection")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sergei Nizovtsev <snizovtsev@cloudlinux.com>
> Assisted-by: Claude:claude-opus-4-8

Applied now.  Thanks.


Takashi

      reply	other threads:[~2026-11-12 12:36 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12  9:48 [PATCH] ALSA: caiaq: Kill EP1 URB before unregistering the input device Sergei Nizovtsev
2026-11-12 12:36 ` Takashi Iwai [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87mrrerzu2.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=snizovtsev@cloudlinux.com \
    --cc=stable@vger.kernel.org \
    --cc=tiwai@suse.com \
    --cc=zonque@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.