All of lore.kernel.org
 help / color / mirror / Atom feed
From: syzbot <syzbot+c90273bf9017ef1462af@syzkaller.appspotmail.com>
To: linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com
Subject: Forwarded: [PATCH] usb: xhci: validate CAPLENGTH in xhci_gen_setup()
Date: Fri, 21 Aug 2026 06:15:17 -0700	[thread overview]
Message-ID: <6a884f65.dbb3a75c.13dd47.001c.GAE@google.com> (raw)
In-Reply-To: <6a8803bf.dbb3a75c.13dd47.000a.GAE@google.com>

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH] usb: xhci: validate CAPLENGTH in xhci_gen_setup()
Author: erdaitianjiao@gmail.com

#syz test

xhci_hcd can be bound to arbitrary PCI devices via the
driver_override sysfs knob. When this happens to a device whose
MMIO registers are not xHCI capability registers,
xhci_gen_setup() reads CAPLENGTH from the foreign register
layout and uses it as a byte offset to compute op_regs.

A non-xHCI device can return a CAPLENGTH value that is
  - not large enough to fit the capability register block, or
  - not 4-byte aligned (e.g. the NVMe CAP register's low byte is
    0xff, which becomes CAPLENGTH = 0xff).

The unaligned case is especially harmful on arm64: MMIO is
Device memory and Device-nGnRE accesses require natural
alignment, so readl(&op_regs->command) faults with an
alignment exception even when the address is within the
ioremapped region.

Validate CAPLENGTH in xhci_gen_setup() and fail probe with
-ENODEV if the value is smaller than 0x20 (capability registers
are 32 bytes per the xHCI spec), not 4-byte aligned, or leaves
no room for the operational register space within the mapped
region.

The run_regs_off read on the next line has the same shape, but
is not reachable on the xhci_halt code path and is left
untouched here.

Reproduced on a QEMU virt machine with a syzkaller repro that
unbinds the NVMe driver on 0000:00:02.0 and binds xhci_hcd via
driver_override. Before this patch the kernel Oopses and
panics; after, the probe is rejected cleanly (verified with 46
consecutive probe attempts, zero Oopses).

Reported-by: syzbot+c90273bf9017ef1462af@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?id=44c85514940262c7e2fad6f8fd0c07d8f2884154
Fixes: 552e0c4f12fe ("usb/xhci: move xhci_gen_setup() away from -pci.")
Signed-off-by: erdaitianjiao <erdaitianjiao@gmail.com>
---
 drivers/usb/host/xhci.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 091c82ca8ee2..fb0075d0530f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5432,7 +5432,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
 	 */
 	struct device		*dev = hcd->self.sysdev;
 	int			retval;
-	u32			hcs_params1;
+	u32			hcs_params1, capbase;
 
 	/* Accept arbitrarily long scatter-gather lists */
 	hcd->self.sg_tablesize = ~0;
@@ -5453,8 +5453,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
 	mutex_init(&xhci->mutex);
 	xhci->main_hcd = hcd;
 	xhci->cap_regs = hcd->regs;
-	xhci->op_regs = hcd->regs +
-		HC_LENGTH(readl(&xhci->cap_regs->hc_capbase));
+	capbase = readl(&xhci->cap_regs->hc_capbase);
+	if (HC_LENGTH(capbase) < 0x20 ||
+	    (HC_LENGTH(capbase) & 0x3) ||
+	    (hcd->rsrc_len &&
+	     HC_LENGTH(capbase) + sizeof(struct xhci_op_regs) > hcd->rsrc_len)) {
+		xhci_err(xhci, "Invalid CAPLENGTH %#x (rsrc_len %#lx)\n",
+			 HC_LENGTH(capbase), (unsigned long)hcd->rsrc_len);
+		return -ENODEV;
+	}
+	xhci->op_regs = hcd->regs + HC_LENGTH(capbase);
 	xhci->run_regs = hcd->regs +
 		(readl(&xhci->cap_regs->run_regs_off) & RTSOFF_MASK);
 	/* Cache read-only capability registers */
-- 
2.55.0


  parent reply	other threads:[~2026-08-21 13:15 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-21  7:52 [syzbot] [usb?] BUG: unable to handle kernel paging request in xhci_halt syzbot
2026-08-21 12:14 ` Forwarded: Re: [PATCH] usb: xhci: validate CAPLENGTH in xhci_gen_setup() syzbot
2026-08-21 12:52 ` Forwarded: Re: [syzbot] [usb?] BUG: unable to handle kernel paging request in xhci_halt syzbot
2026-08-21 13:15 ` syzbot [this message]
2026-08-21 13:40 ` Forwarded: Re: #syz test (re-run after sandbox SYZFAIL) syzbot
2026-08-21 14:14 ` Forwarded: [PATCH] usb: xhci: validate CAPLENGTH in xhci_gen_setup() syzbot

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=6a884f65.dbb3a75c.13dd47.001c.GAE@google.com \
    --to=syzbot+c90273bf9017ef1462af@syzkaller.appspotmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=syzkaller-bugs@googlegroups.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.