[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20251209071248.3575845-1-zzzccc427@gmail.com>
Date: Tue, 9 Dec 2025 15:12:48 +0800
From: Cen Zhang <zzzccc427@...il.com>
To: luiz.dentz@...il.com,
marcel@...tmann.org
Cc: linux-kernel@...r.kernel.org,
linux-bluetooth@...r.kernel.org,
pav@....fi,
baijiaju1990@...il.com,
r33s3n6@...il.com,
gality369@...il.com,
zhenghaoran154@...il.com,
Cen Zhang <zzzccc427@...il.com>
Subject: [PATCH] Bluetooth: btintel: serialize hw error recovery with req_lock
btintel_hw_error() issues two __hci_cmd_sync() calls to reset the
controller and fetch the Intel exception report. Unlike the shutdown
path, this helper ran without hci_req_sync_lock(), so it could race
against hci_dev_do_close() and both sides would manipulate
hdev->req_status/req_rsp concurrently.When the close path freed the
shared response buffer first, the still running hw_error path hit a
slab-use-after-free inside kfree_skb() (skb_unref → atomic_read) and
KASAN reported the crash in the trace.
Acquire hci_req_sync_lock() around the hw_error recovery sequence and
make sure all error/cleanup paths release it. This serializes the Intel
handler with every other synchronous command issuer and prevents the
req_* bookkeeping from being double-touched.
Below is the data race report and the kasan report:
BUG: data-race in __hci_cmd_sync_sk / btintel_shutdown_combined
read of hdev->req_rsp at net/bluetooth/hci_sync.c:199 by task kworker/u17:1/83
write/free of same SKB at drivers/bluetooth/btintel.c:3660 by task ioctl/22580
Call Trace (reader):
__hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200
__hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223
btintel_hw_error+0x114/0x670 drivers/bluetooth/btintel.c:254
hci_error_reset+0x348/0xa30 net/bluetooth/hci_core.c:1030
...
Call Trace (writer):
btintel_shutdown_combined+0xd0/0x360 drivers/bluetooth/btintel.c:3648
hci_dev_close_sync+0x9ae/0x2c10 net/bluetooth/hci_sync.c:5246
hci_dev_do_close+0x232/0x460 net/bluetooth/hci_core.c:526
...
BUG: KASAN: slab-use-after-free in sk_skb_reason_drop+0x43/0x380 net/core/skbuff.c:1202
Read of size 4 at addr ffff888144a738dc by task kworker/u17:1/83
Call Trace:
__hci_cmd_sync_sk+0x12f2/0x1c30 net/bluetooth/hci_sync.c:200
__hci_cmd_sync+0x55/0x80 net/bluetooth/hci_sync.c:223
btintel_hw_error+0x186/0x670 drivers/bluetooth/btintel.c:260
...
Allocated by task 84:
skb_clone+0x212/0x3a0 net/core/skbuff.c:2049
hci_event_packet+0x66c/0x2da0 net/bluetooth/hci_event.c:7614
...
Freed by task 22580:
btintel_shutdown_combined+0xd0/0x360 drivers/bluetooth/btintel.c:3648
hci_dev_close_sync+0x9ae/0x2c10 net/bluetooth/hci_sync.c:5246
hci_dev_do_close+0x232/0x460 net/bluetooth/hci_core.c:526
...
Signed-off-by: Cen Zhang <zzzccc427@...il.com>
---
drivers/bluetooth/btintel.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 9d29ab811..baa3ee510 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -251,10 +251,12 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
bt_dev_err(hdev, "Hardware error 0x%2.2x", code);
+ hci_req_sync_lock(hdev);
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reset after hardware error failed (%ld)",
PTR_ERR(skb));
+ hci_req_sync_unlock(hdev);
return;
}
kfree_skb(skb);
@@ -263,18 +265,22 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)",
PTR_ERR(skb));
+ hci_req_sync_unlock(hdev);
return;
}
if (skb->len != 13) {
bt_dev_err(hdev, "Exception info size mismatch");
kfree_skb(skb);
+ hci_req_sync_unlock(hdev);
return;
}
bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1));
kfree_skb(skb);
+
+ hci_req_sync_unlock(hdev);
}
EXPORT_SYMBOL_GPL(btintel_hw_error);
--
2.34.1
Powered by blists - more mailing lists