[PATCH] Bluetooth: btintel_pcie: Fix NULL hdev dereference in debug register dump
From: Chia-Lin Kao (AceLan)
Date: Tue Oct 13 2026 - 19:36:08 EST
The MSI-X interrupts are set up in btintel_pcie_config_pcie() and the
controller is brought out of reset in btintel_pcie_enable_bt(), both
long before btintel_pcie_setup_hdev() allocates the hci_dev. On top of
that, data->hdev is only published after hci_register_dev() succeeds.
Until then, any interrupt that reaches an error path sees a NULL
data->hdev.
btintel_pcie_dump_debug_registers() is called from those error paths
with data->hdev and dereferences it immediately via hci_get_drvdata().
If the controller raises such an interrupt during probe, the IRQ thread
oopses. The bt_dev_*() logging helpers are fine with a NULL hdev (they
print "null" as the device name), so the crash is only in the register
dump.
This was seen on an HP ZBook X G2i (8086:e376) with v7.3-rc7, where the
GP1 mailbox interrupt was handled right after the device was enabled:
btintel_pcie 0000:00:14.7: enabling device (0000 -> 0002)
Bluetooth: null: Received gp1 mailbox interrupt
Oops: general protection fault, kernel NULL pointer dereference 0xda0
CPU: 11 UID: 0 PID: 671 Comm: irq/213-btintel
RIP: 0010:btintel_pcie_dump_debug_registers+0x20/0x910 [btintel_pcie]
Call Trace:
btintel_pcie_irq_msix_handler+0x1ca/0x6b0 [btintel_pcie]
irq_thread_fn+0x26/0x70
irq_thread+0x1b1/0x300
The IRQ thread then dies in do_exit() and the module load and the
following power off block behind it. The GP1 handler no longer calls
the dump helper in current linux-next, but the GP0 handler still does
for the "Controller in error state" and "Controller in lockdown state"
cases, which have the same exposure during probe.
Return early from btintel_pcie_dump_debug_registers() when there is no
hci_dev yet. The register dump is delivered through hci_recv_diag(),
so there is nowhere to send it without an hdev anyway; the preceding
bt_dev_err() has already reported the event.
Fixes: 190377500fde ("Bluetooth: btintel_pcie: Dump debug registers on error")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@xxxxxxxxxxxxx>
---
drivers/bluetooth/btintel_pcie.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 3a555aa50c87..fcdea1302cf7 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -433,12 +433,21 @@ static void btintel_pcie_prepare_tx(struct txq *txq, u16 tfd_index,
static inline void btintel_pcie_dump_debug_registers(struct hci_dev *hdev)
{
- struct btintel_pcie_data *data = hci_get_drvdata(hdev);
+ struct btintel_pcie_data *data;
u16 cr_hia, cr_tia;
u32 reg, mbox_reg;
struct sk_buff *skb;
u8 buf[80];
+ /* The interrupts are enabled before the hci_dev is allocated and
+ * data->hdev is published only after hci_register_dev() succeeds, so
+ * an interrupt handler can get here with a NULL hdev.
+ */
+ if (!hdev)
+ return;
+
+ data = hci_get_drvdata(hdev);
+
skb = alloc_skb(1024, GFP_ATOMIC);
if (!skb)
return;
--
2.53.0