Message ID | 20240531110835.3800904-1-namcao@linutronix.de (mailing list archive) |
---|---|
State | New |
Delegated to: | Bjorn Helgaas |
Headers | show |
Series | PCI: hotplug: shpchp: Prevent NULL pointer dereference during probe | expand |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 56c7795ed890..14cf9e894201 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -262,6 +262,12 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (acpi_get_hp_hw_control_from_firmware(pdev)) return -ENODEV; + if (!pdev->subordinate) { + /* Can happen if we run out of bus numbers during probe */ + pci_err(pdev, "Hotplug bridge without secondary bus, ignoring\n"); + return -ENODEV; + } + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) goto err_out_none;
pci_dev->subordinate pointer can be NULL if we run out of bus number. The driver deferences this pointer without checking, and the kernel crashes. This crash can be reproduced by starting a QEMU instance: qemu-system-x86_64 -machine pc-q35-2.10 \ -kernel bzImage \ -drive "file=img,format=raw" \ -m 2048 -smp 1 -enable-kvm \ -append "console=ttyS0 root=/dev/sda debug" \ -nographic \ -device pcie-root-port,bus=pcie.0,slot=1,id=rp1 \ -device pcie-pci-bridge,id=br1,bus=rp1 Then hot-add a bridge with the QEMU command: device_add pci-bridge,id=br2,bus=br1,chassis_nr=1,addr=1 Then the kernel crashes: shpchp 0000:02:01.0: enabling device (0000 -> 0002) shpchp 0000:02:01.0: enabling bus mastering BUG: kernel NULL pointer dereference, address: 00000000000000da [snip] Call Trace: <TASK> ? show_regs+0x63/0x70 ? __die+0x23/0x70 ? page_fault_oops+0x17a/0x480 ? shpc_init+0x3fb/0x9d0 ? search_module_extables+0x4e/0x80 ? shpc_init+0x3fb/0x9d0 ? kernelmode_fixup_or_oops+0x9b/0x120 ? __bad_area_nosemaphore+0x16e/0x240 ? bad_area_nosemaphore+0x11/0x20 ? do_user_addr_fault+0x2a3/0x610 ? exc_page_fault+0x6d/0x160 ? asm_exc_page_fault+0x2b/0x30 ? shpc_init+0x3fb/0x9d0 shpc_probe+0x92/0x390 NULL check this pointer first before proceeding. If there is no secondary bus number, there is no point in initializing this hot-plug controller, so just bails out. Signed-off-by: Nam Cao <namcao@linutronix.de> Cc: stable@vger.kernel.org # all --- This one exists since beginning of git history. So I didn't bother with a Fixes: tag. This patch is almost a copy-paste from pciehp --- drivers/pci/hotplug/shpchp_core.c | 6 ++++++ 1 file changed, 6 insertions(+)