[PATCH] scsi: stex: Fix NULL pointer dereference in stex_hard_reset()
From: Yang Zi
Date: Tue Aug 25 2026 - 05:27:11 EST
stex_hard_reset() reads the PCI bridge device via hba->pdev->bus->self
and passes it to pci_read_config_byte()/pci_write_config_byte() without
checking whether it is NULL. When the controller is attached to a root
bus (or otherwise has no bridge device), bus->self is NULL, and
pci_read_config_byte(NULL, ...) dereferences it in
pci_dev_is_disconnected(), triggering a NULL pointer dereference.
KASAN report:
BUG: KASAN: null-ptr-deref in pci_dev_is_disconnected include/linux/pci.h:2676 [inline]
BUG: KASAN: null-ptr-deref in pci_read_config_byte+0x23/0x90 drivers/pci/access.c:562
Read of size 4 at addr 00000000000000c4 by task scsi_eh_6/2005
RIP: 0010:pci_dev_is_disconnected include/linux/pci.h:2676 [inline]
RIP: 0010:pci_read_config_byte+0x23/0x90 drivers/pci/access.c:562
...
stex_hard_reset drivers/scsi/stex.c:1322 [inline] [stex]
stex_do_reset+0x3da6/0x6490 drivers/scsi/stex.c:1424 [stex]
Skip the secondary bus reset when there is no bridge device; the rest of
the reset sequence (config space save/restore and the PCI_COMMAND poll)
does not depend on bus->self and still runs.
Signed-off-by: Yang Zi <2959243019@xxxxxx>
---
drivers/scsi/stex.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 6aeeb338633d..f1dff2cc6086 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -1319,17 +1319,20 @@ static void stex_hard_reset(struct st_hba *hba)
/* Reset secondary bus. Our controller(MU/ATU) is the only device on
secondary bus. Consult Intel 80331/3 developer's manual for detail */
bus = hba->pdev->bus;
- pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &pci_bctl);
- pci_bctl |= PCI_BRIDGE_CTL_BUS_RESET;
- pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
+ if (bus->self) {
+ pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &pci_bctl);
+ pci_bctl |= PCI_BRIDGE_CTL_BUS_RESET;
+ pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
- /*
- * 1 ms may be enough for 8-port controllers. But 16-port controllers
- * require more time to finish bus reset. Use 100 ms here for safety
- */
- msleep(100);
- pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
- pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
+ /*
+ * 1 ms may be enough for 8-port controllers. But 16-port
+ * controllers require more time to finish bus reset. Use 100 ms
+ * here for safety
+ */
+ msleep(100);
+ pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+ pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl);
+ }
for (i = 0; i < MU_HARD_RESET_WAIT; i++) {
pci_read_config_word(hba->pdev, PCI_COMMAND, &pci_cmd);