[PATCH] thunderbolt: verify PCI resource type and size in nhi_probe()
Dmitry Antipov <[email protected]> Fri, 7 Aug 2026 11:37:57 +0300
| Newsgroups | org.kernel.vger.linux-usb |
|---|---|
| Message-ID | <[email protected]> |
Syzbot reproducer at [1] enforces the kernel to probe PCI device 00:02.0 as Thunderbolt NHI. On QEMU/aarch64 'virt' machine, the device (at least with qemu >= 11.0.0) is: 00:02.0 Class 0100: Device 1af4:1001 Subsystem: Device 1af4:0002 Flags: bus master, fast devsel, latency 0, IRQ 47 I/O ports at 1000 [size=128] <-- Hmmm... Memory at 10041000 (32-bit, non-prefetchable) [size=4K] Memory at 8000004000 (64-bit, prefetchable) [size=16K] So call to 'pcim_iomap_region(pdev, 0, ...)' in 'nhi_pci_probe()' maps this 128-bytes I/O ports area, and call to 'ioread32(nhi->iobase + REG_CAPS)' in 'nhi_probe()' issues an invalid access at REG_CAPS (0x39640) offset. Since NHI's typical register window size is 256K, simple sanity check whether 1) the region is a memory rather than I/O ports and 2) the region is 256K at least should be enough to prevent from such a scenario. [1] https://syzkaller.appspot.com/text?tag=ReproC&x=1564acc6580000 Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=901ca72278dfd89daf58 Fixes: 16603153666d ("thunderbolt: Add initial cactus ridge NHI support") Signed-off-by: Dmitry Antipov <[email protected]> --- drivers/thunderbolt/nhi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 0f795ea58756..724263c17b3e 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -1186,6 +1186,7 @@ static struct tb *nhi_select_cm(struct tb_nhi *nhi) int nhi_probe(struct tb_nhi *nhi) { struct device *dev = nhi->dev; + struct pci_dev *pdev; struct tb *tb; int res; @@ -1195,6 +1196,12 @@ int nhi_probe(struct tb_nhi *nhi) if (!nhi->ops->init_interrupts) return dev_err_probe(dev, -EINVAL, "missing required NHI ops\n"); + pdev = to_pci_dev(dev); + if (!pci_resource_is_mem(pdev, 0)) + return dev_err_probe(dev, -ENODEV, "invalid resource type\n"); + if (pci_resource_len(pdev, 0) < 0x40000) + return dev_err_probe(dev, -ENODEV, "invalid resource size\n"); + nhi->hop_count = ioread32(nhi->iobase + REG_CAPS) & 0x3ff; dev_dbg(dev, "total paths: %d\n", nhi->hop_count); -- 2.55.0