Re: [syzbot] [bluetooth?] [usb?] memory leak in __hci_cmd_sync_sk

From: shaurya

Date: Tue Nov 18 2025 - 21:46:39 EST


#syz test:
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master From da73ec851aa5ec19b429c4cf8b9e2cd6a42e6e1e Mon Sep 17 00:00:00 2001
From: Shaurya Rane <ssrane_b23@xxxxxxxxxxxxx>
Date: Wed, 19 Nov 2025 08:01:33 +0530
Subject: [PATCH] Bluetooth: hci_sync: fix memory leak in __hci_cmd_sync_sk

Fix a memory leak in __hci_cmd_sync_sk where allocated request command
SKBs are not properly cleaned up when the function fails.

The issue occurs when hci_cmd_sync_alloc() successfully allocates an SKB
and it gets queued via hci_cmd_sync_add(), but then __hci_cmd_sync_sk()
fails due to timeout, interruption, or cancellation. In these error
paths, the req_skb that was cloned and stored in hdev->req_skb is not
freed, leading to memory leaks.

The memory leak can be reproduced when __hci_cmd_sync_sk() allocates
and queues an HCI command SKB, and hci_req_sync_run() transfers this
SKB to hdev->cmd_q and clones it to hdev->req_skb. If the subsequent
wait_event_interruptible_timeout() call fails (due to timeout or
interruption), the function returns an error without hdev->req_skb
ever being cleaned up.

The fix ensures that when __hci_cmd_sync_sk() returns an error, any
pending request command SKB in hdev->req_skb is properly freed before
returning. This matches the cleanup pattern used elsewhere in the HCI
sync code.

Reported-by: syzbot+f098d64cc684b8dbaf65@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=f098d64cc684b8dbaf65
Signed-off-by: Shaurya Rane <ssrane_b23@xxxxxxxxxxxxx>
---
net/bluetooth/hci_sync.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 6e76798ec786..fbaa5749ad7b 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -203,6 +203,11 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,

if (err < 0) {
kfree_skb(skb);
+ /* Clean up any pending request command */
+ if (hdev->req_skb) {
+ kfree_skb(hdev->req_skb);
+ hdev->req_skb = NULL;
+ }
return ERR_PTR(err);
}

--
2.34.1