Re: [PATCH] thunderbolt: verify PCI resource type and size in nhi_probe()
Mika Westerberg <[email protected]> Fri, 7 Aug 2026 11:58:31 +0200
| Newsgroups | org.kernel.vger.linux-usb |
|---|---|
| Message-ID | <[email protected]> |
Hi, On Fri, Aug 07, 2026 at 11:37:57AM +0300, Dmitry Antipov wrote: > 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] Yeah, I'm not entirely sure we want to start "fixing" issues like these where it's clearly not a USB4/TB NHI. IMHO If user forces the driver somehow to bind to this unrelated device then she/he got what asked for. > 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