mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] HID: nintendo-switch2-usb: check URB before use and reset state on free
@ 2026-11-08 22:29 Noah Weinberger
  2026-11-10  2:38 ` Vicki Pfau
  0 siblings, 1 reply; 2+ messages in thread
From: Noah Weinberger @ 2026-11-08 22:29 UTC (permalink / raw)
  To: djogorchock, vi, jikos, bentiss; +Cc: linux-input, linux-kernel

Hello,

Proposed-fix limitation: the checks below do not establish URB or
interface lifetime across the pointer check, lock release, and subsequent
use. These proposed changes may therefore not resolve the teardown race
or the late-work use-after-free described below. Please review the
locking and work/interface lifetime before treating this as a complete
fix; this is an incomplete proposal for maintainer review, not a
validated resolution.

switch2_bulk_in() calls schedule_work() after dropping bulk_in_lock, so
the work can be queued after switch2_usb_free_in_urbs() has returned
from cancel_work_sync(). free_in_urbs() NULLs bulk_in[i].urb but never
resets bulk_in[i].state, so the late work still sees NS2_URB_IN and
dereferences urb->urb->transfer_buffer / urb->urb->actual_length on a
NULL pointer - the existing !urb->urb check sits after those
dereferences:

    if (urb->state != NS2_URB_IN)
            continue;
    spin_unlock_irqrestore(...);
    if (ns2_usb->cfg.parent) {
            err = switch2_receive_command(..., urb->urb->transfer_buffer,
                                    urb->urb->actual_length);   <-- NULL deref
    ...
    if (!urb->urb)   <-- too late

A malicious or misbehaving controller (or an unplug racing active
traffic) wins a narrow window to trigger this; the outcome is an oops
in workqueue context, and a use-after-free if the work runs after the
interface data is released. The patch re-checks urb->urb under the lock
before using it and resets the URB state when freeing, mirroring what
switch2_usb_shutdown() already does.

Affected version/commit: mainline fa4ad798f6f681031775266044ba1b0cf3c670bd (v7.4-rc1, 2026-11-07), drivers/hid/hid-nintendo-switch2-usb.c:51-121 (completion), 209-240 (free path), 288-316 (work).
New driver merged in this window (zero prior field exposure).

This was found during an assisted (AI-supported) static source review of
mainline fa4ad798f6f681031775266044ba1b0cf3c670bd (v7.4-rc1, 2026-11-07); every code path cited below was re-verified by the
reporter against that tree. The patch below has NOT been compiled and has
NOT been runtime tested, and no reproducer was produced - the triggering
conditions are described above instead. Please treat this as a report for
verification rather than a battle-tested fix.

Reported-by: Noah Weinberger <noahweinberger2003@proton.me>
---
diff --git a/drivers/hid/hid-nintendo-switch2-usb.c b/drivers/hid/hid-nintendo-switch2-usb.c
index 8b3b684..c846cef 100644
--- a/drivers/hid/hid-nintendo-switch2-usb.c
+++ b/drivers/hid/hid-nintendo-switch2-usb.c
@@ -231,6 +231,7 @@ static void switch2_usb_free_in_urbs(struct switch2_usb *ns2_usb)
 
 		ns2_usb->bulk_in[i].urb = NULL;
 		ns2_usb->bulk_in[i].data = NULL;
+		ns2_usb->bulk_in[i].state = NS2_URB_FREE;
 		spin_unlock_irqrestore(&ns2_usb->bulk_in_lock, flags);
 
 		usb_kill_urb(urb);
@@ -298,6 +299,11 @@ static void switch2_usb_message_in_work(struct work_struct *work)
 		urb = &ns2_usb->bulk_in[i];
 		if (urb->state != NS2_URB_IN)
 			continue;
+			/* urb->urb is NULLed by switch2_usb_free_in_urbs() while we
+			 * may still run; re-check under the lock before using it.
+			 */
+			if (!urb->urb)
+				continue;
 		spin_unlock_irqrestore(&ns2_usb->bulk_in_lock, flags);
 
 		if (ns2_usb->cfg.parent) {


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

end of thread, other threads:[~2026-11-10  2:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-08 22:29 [PATCH] HID: nintendo-switch2-usb: check URB before use and reset state on free Noah Weinberger
2026-11-10  2:38 ` Vicki Pfau

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

all inboxes | Powered by JetHome®