From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 01C2E52F289 for ; Tue, 13 Oct 2026 15:27:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791905248; cv=none; b=hxVsp6WtZc8M8bjCf7Whupb0SaeDqsQsHGUcfY8fWfMkmJPsjZuMg1BqJVaFTCgWNLoa4PgtxK/c2SOc3051mtXfY3K8+zeDG+WyAo4dXQhkjdT1iiz7R69r7y8ukURMJOzEzrYd1+fZDgfOVN/jMSR5MXpoGyAd3TUpXkCx+M4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791905248; c=relaxed/simple; bh=AU9kWaS+ah7/2Sq1BZDH+PM81Z6iFFmtW0d0gPHW3tk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u7Gm06Hm63MXPBF/vFI//nhvuLHEM+VWV0+Op0OstbzHspZ4JIBY/aEDG56s4kALBydM08rCNvu2+rwcXndzpoyTojDuR7iZaptFvgf0bfPRVVh2myq/5/tnFJDHLTwMZN+5ZssfTg8aiBFpKaE+y1rEgPWCerFYIfphtskAesk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iH5CDae1; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iH5CDae1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5ADFC1F00898; Tue, 13 Oct 2026 15:27:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1791905246; bh=dQQ3DjHUoGzwR1QEyHkVHhhLMjyU7jEjaTsZS923nBs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iH5CDae1QLpVrHqq/b7ZdoHD79uTDw9d3XCejsxwRIvbSQGFbgY+1Y0QVMETv8Su8 x6bAt9898R1uX22TNhmRV8s5xnLs9Z6py5FKau9OJhOJSdU9vf6I8NhFSB1a9dEOEG hxcQmXc1YUQE2I+j3lGJPvC++NUmGIlGZwv9RD3KuzsqHiWY+a57H/5+K51pVQEqhk LXtoG7iU/lRrP2Z6UOSGIkrEcx3YxAKiBFQ473h3lJD9TRDtSbTr+ZofyIUku7Bcr/ AJyzf93EVEf41eMKBtPE64jtDUY+8MmvN1gX9X5eJolAGbms4T2gKIG68kvlbAIy1k QJYNfUannj2Lw== From: Sasha Levin To: stable@vger.kernel.org Cc: Chengfeng Ye , Luiz Augusto von Dentz , Sasha Levin Subject: [PATCH 6.12.y] Bluetooth: hci_sync: Fix command skb lifetime during scan setup Date: Tue, 13 Oct 2026 11:27:25 -0400 Message-ID: <20261013152714.130958-1-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <2026101206-hurray-deftly-6159@gregkh> References: <2026101206-hurray-deftly-6159@gregkh> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Chengfeng Ye [ Upstream commit 9af12272061d206af8bc3e40215cb694421ab73a ] During PA sync scan setup, hci_le_set_ext_scan_param_sync() gets the address used for the PA_LINK lookup from hci_sent_cmd_data(). The returned pointer borrows storage from sent_cmd or req_skb, without holding a reference to either skb. The scan worker runs on req_workqueue while hci_cmd_work() runs on the separate device workqueue. After the scan worker loads sent_cmd, the command worker can free and replace it before hci_sent_cmd_data() dereferences the skb. The command payload can also be freed between returning from the helper and comparing the address. The connection lookup's RCU critical section does not protect the command skb. KASAN reported: BUG: KASAN: slab-use-after-free in hci_sent_cmd_data+0x27c/0x2f0 Workqueue: hci0 hci_cmd_sync_work Call Trace: hci_sent_cmd_data+0x27c/0x2f0 hci_le_set_scan_param_sync+0x43a/0x850 hci_passive_scan_sync+0xb09/0x1460 hci_update_passive_scan_sync+0x47c/0x6e0 hci_le_pa_create_sync+0x200/0xa70 hci_cmd_sync_work+0x13c/0x290 Allocated by task 95: skb_clone+0x13f/0x340 hci_cmd_work+0x2a9/0x7e0 Freed by task 95: kmem_cache_free+0xba/0x3a0 hci_cmd_work+0x29c/0x7e0 Use hdev->lock to serialize the address snapshot with sent_cmd replacement. Protect req_skb replacement and completion cleanup with the same lock because the helper falls back to that skb. Copy the address before releasing the lock and use the copy for the existing RCU-protected connection lookup. Release the mutex before sending or waiting for commands, preserving the lookup and completion ordering. Fixes: 22cbf4f84c00 ("Bluetooth: hci_sync: Use QoS to determine which PHY to scan") Cc: stable@vger.kernel.org Assisted-by: GPT-6 Astra Signed-off-by: Chengfeng Ye Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- net/bluetooth/hci_core.c | 4 ++++ net/bluetooth/hci_sync.c | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 95900c2325631..ff3ccb33da0c7 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4155,9 +4155,11 @@ static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) bt_dev_dbg(hdev, "skb %p", skb); + hci_dev_lock(hdev); kfree_skb(hdev->sent_cmd); hdev->sent_cmd = skb_clone(skb, GFP_KERNEL); + hci_dev_unlock(hdev); if (!hdev->sent_cmd) { skb_queue_head(&hdev->cmd_q, skb); queue_work(hdev->workqueue, &hdev->cmd_work); @@ -4178,8 +4180,10 @@ static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) if (READ_ONCE(hdev->req_status) == HCI_REQ_PEND && !hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) { + hci_dev_lock(hdev); kfree_skb(hdev->req_skb); hdev->req_skb = skb_get(hdev->sent_cmd); + hci_dev_unlock(hdev); } return err; diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index f4dea6fffa727..6d7caf00fc897 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -32,8 +32,10 @@ static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, WRITE_ONCE(hdev->req_status, HCI_REQ_DONE); /* Free the request command so it is not used as response */ + hci_dev_lock(hdev); kfree_skb(hdev->req_skb); hdev->req_skb = NULL; + hci_dev_unlock(hdev); if (skb) { struct sock *sk = hci_skb_sk(skb); @@ -3058,13 +3060,19 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, */ if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) { struct hci_cp_le_add_to_accept_list *sent; + bdaddr_t bdaddr; + hci_dev_lock(hdev); sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST); + if (sent) + bacpy(&bdaddr, &sent->bdaddr); + hci_dev_unlock(hdev); + if (sent) { struct hci_conn *conn; conn = hci_conn_hash_lookup_ba(hdev, PA_LINK, - &sent->bdaddr); + &bdaddr); if (conn) { struct bt_iso_qos *qos = &conn->iso_qos; -- 2.53.0