From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ot1-f72.google.com (mail-ot1-f72.google.com [209.85.210.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A4A433B6EF for ; Fri, 21 Aug 2026 15:34:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.72 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787326491; cv=none; b=RK7Ku8s/QBMSN4zGSJVvSsw/JkktFzpJ1J96GQKznSy4LT1BulVm8Eir29MTi4Uy3QPT5V8LOALsccV9A8PXyW6ZeTFBwv90BcPsB+RBHspsdVVXWjbByK98qpes8TBewadfopddTe7yn9ueWe0kA8dfKLDOCR2Ns+4gDObeJks= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787326491; c=relaxed/simple; bh=leSDWVxObA//A5UbGzhn3GW0rA6uTtNZSXD2JlDiUvg=; h=MIME-Version:Date:In-Reply-To:Message-ID:Subject:From:To: Content-Type; b=JlNOGKCn/EmXykATaHe3f/Fi4ntgbv/0x8KxL+oR730/NHrc1+Oq3jst+3gbsDoGeUkQd80FhoMEpGHuy4opxHaRvYoQ0OJ3c4ayS18uCc9nYSJEH+bazZjSM+3ZDSbZmD/eI8fJyg9th780ZG1vPkhw6JRN6MzAMgSkORzOIP4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com; arc=none smtp.client-ip=209.85.210.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com Received: by mail-ot1-f72.google.com with SMTP id 46e09a7af769-7ec3b429610so2150384a34.1 for ; Fri, 21 Aug 2026 08:34:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787326488; x=1787931288; h=content-type:to:from:subject:message-id:in-reply-to:date :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=9Zjz76x72j6Om11Km16BTYs/c8Jn4XMnq+I4hKUCl/Q=; b=GyOx2DUn13FHMDPFEM52qwTQKLiTe2r1Ghaz2CYMWWJdiPR7RaB7fPFf+IaOX7ydSY RRXGDl84JZRtzeDxnUtUdGzpHBEnSvSO4/coRmXtrnrJiurcbunN4uF31jdMxE6yDTwO WXtSlssclPaDA74fynrB5CNbN37RSYtHEWpVY3mQua0SnG+nZ0NfzU1yN47D5tDUBq4j 7fm6wk3p4Dsya2Vkmmi96LKoQ8WUYzOveAlS+7D2NztEhuqjjwaSLW8zilJCe3aVMoyD KlwBQynd03VoX+geypwICDM9fJFdgY45sLZnYPLHpWO2EP8OB70G1T+ACQ3oN9oRrV4R 0zew== X-Gm-Message-State: AOJu0Yzf0VLISQU66Y/VsoMgD9X3uruIJLVJs/LY7YlflmjNPrIR6JCE OoAFordnhySCAIuWdscgL2jbMH9MLOls5ufwFg1rYqw2Y4Ja4lmHabLP6Z2/tlIAgTT7+qriPcX QiqJS7+csx0hPa8TuvpsYXawg8q4hquJgOIqCVR4lO8y1qdzvlf/2zBWU0+8= Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Received: by 2002:a05:6820:4385:b0:6aa:2fbf:bf60 with SMTP id 006d021491bc7-6b159470ad9mr7129793eaf.34.1787326488492; Fri, 21 Aug 2026 08:34:48 -0700 (PDT) Date: Fri, 21 Aug 2026 08:34:48 -0700 In-Reply-To: <6a8803bf.dbb3a75c.13dd47.000a.GAE@google.com> X-Google-Appengine-App-Id: s~syzkaller X-Google-Appengine-App-Id-Alias: syzkaller Message-ID: <6a887018.dbb3a75c.13dd47.001e.GAE@google.com> Subject: Forwarded: [PATCH] usb: xhci: validate CAPLENGTH in xhci_gen_setup() From: syzbot To: linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com Content-Type: text/plain; charset="UTF-8" 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 --- 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