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 1F1AD3909B5; Sat, 17 Oct 2026 16:24:40 +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=1792254281; cv=none; b=hp8XKCbxKarrDQ2KBOj+oIHk0Fh55zN3HAsowecURN1+rB1rWgPXEIfs6Oqrw7EWQ3Eg7Os1iJbNxynvOLIoZXQ3QzLaVuE/3M+mFgnyRC5a47RIroqyp5WEUnE+J0FlJPrz2iZ+bAxT5F4bmZwCiC4E3RqJkXvJFv4DaCjxYTQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792254281; c=relaxed/simple; bh=75S7nZg7Egiv0ZPuOA1ol23rkjuL4jmJFYS4GYS8vSQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RWnnfv9w35LySG3tzhEf4UD990mtZdd8aJzTXIDAcXuC5yR81ISFD0ve0HbNOXBdmzI0bJIIbBDTJrZz/afbj70USQ380jz13MX0grNUXzfv9HJ+ADiZBgyhKshT66Y3FO+Dc5mTfmihVxfvcqP0F/VPg/LTqD0M8xJ4B1VJ89s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=SaTNmX/l; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="SaTNmX/l" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67EB11F000C4; Sat, 17 Oct 2026 16:24:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1792254280; bh=paUReEtg3BMcC6ak8i+S/+WujvBFbcggNcSwXS5sZ7k=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SaTNmX/lXhcbaNCE52siSSLzL8Y0z7ygrZhMNnHJkAaEuVIXpGc8tDBem4P0e3Uv2 hpdqW3TUcvmIHjOXkgjtU6Gh26lBZbOZkidD6ZeaNc4KwWVXHdY0UKzXUuqsKY9tw2 vKGZWncm6lhIiJaDY2GTyvN3J6+wMx1WhQQSTZSw= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Pauli Virtanen , Luiz Augusto von Dentz , Sasha Levin Subject: [PATCH 6.12 396/869] Bluetooth: hci_sync: extend conn_hash lookup critical sections Date: Sat, 17 Oct 2026 17:53:57 +0200 Message-ID: <20261017160047.271754284@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261017160036.979869304@linuxfoundation.org> References: <20261017160036.979869304@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Pauli Virtanen [ Upstream commit d5efd6e4b8b0634af6843178fe1a7dd2b2178a3d ] Using RCU-protected pointers outside the critical sections without refcount is incorrect and may result to UAF. Extend critical section to cover both hci_conn_hash lookup and use of the returned conn. Add surrounding rcu_read_lock() also when return value is not used, in preparation for RCU lockdep requirement to hci_lookup_le_connect(). This avoids concurrent deletion of the conn before we are done dereferencing it. Also, make sure to hold hdev->lock when accessing hdev->accept_list. Fixes: 6d0417e4e1cf ("Bluetooth: hci_conn: Fix not setting conn_timeout for Broadcast Receiver") Signed-off-by: Pauli Virtanen Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- net/bluetooth/hci_sync.c | 42 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index b0ab43145e47f..3e3706231458d 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -1077,14 +1077,19 @@ static int hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa) * In this kind of scenario skip the update and let the random * address be updated at the next cycle. */ + rcu_read_lock(); + if (bacmp(&hdev->random_addr, BDADDR_ANY) && (hci_dev_test_flag(hdev, HCI_LE_ADV) || hci_lookup_le_connect(hdev))) { bt_dev_dbg(hdev, "Deferring random address update"); hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); + rcu_read_unlock(); return 0; } + rcu_read_unlock(); + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_RANDOM_ADDR, 6, rpa, HCI_CMD_TIMEOUT); } @@ -2757,12 +2762,17 @@ static int hci_pause_addr_resolution(struct hci_dev *hdev) /* Cannot disable addr resolution if scanning is enabled or * when initiating an LE connection. */ + rcu_read_lock(); + if (hci_dev_test_flag(hdev, HCI_LE_SCAN) || hci_lookup_le_connect(hdev)) { + rcu_read_unlock(); bt_dev_err(hdev, "Command not allowed when scan/LE connect"); return -EPERM; } + rcu_read_unlock(); + /* Cannot disable addr resolution if advertising is enabled. */ err = hci_pause_advertising_sync(hdev); if (err) { @@ -2900,6 +2910,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) { struct hci_conn *conn; + rcu_read_lock(); + conn = hci_conn_hash_lookup_create_pa_sync(hdev); if (conn) { struct conn_params pa; @@ -2909,6 +2921,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) bacpy(&pa.addr, &conn->dst); pa.addr_type = conn->dst_type; + rcu_read_unlock(); + /* Clear first since there could be addresses left * behind. */ @@ -2918,6 +2932,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) err = hci_le_add_accept_list_sync(hdev, &pa, &num_entries); goto done; + } else { + rcu_read_unlock(); } } @@ -2928,10 +2944,13 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) * the controller. */ list_for_each_entry_safe(b, t, &hdev->le_accept_list, list) { - if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) + rcu_read_lock(); + + if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type)) { + rcu_read_unlock(); continue; + } - /* Pointers not dereferenced, no locks needed */ pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns, &b->bdaddr, b->bdaddr_type); @@ -2939,6 +2958,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) &b->bdaddr, b->bdaddr_type); + rcu_read_unlock(); + /* If the device is not likely to connect or report, * remove it from the acceptlist. */ @@ -3071,6 +3092,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, if (sent) { struct hci_conn *conn; + rcu_read_lock(); + conn = hci_conn_hash_lookup_ba(hdev, PA_LINK, &bdaddr); if (conn) { @@ -3095,8 +3118,12 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, phy++; } + rcu_read_unlock(); + if (num_phy) goto done; + } else { + rcu_read_unlock(); } } } @@ -3347,12 +3374,16 @@ int hci_update_passive_scan_sync(struct hci_dev *hdev) /* If there is at least one pending LE connection, we should * keep the background scan running. */ + bool exists; /* If controller is connecting, we should not start scanning * since some controllers are not able to scan and connect at * the same time. */ - if (hci_lookup_le_connect(hdev)) + rcu_read_lock(); + exists = hci_lookup_le_connect(hdev); + rcu_read_unlock(); + if (exists) return 0; bt_dev_dbg(hdev, "start background scanning"); @@ -3570,6 +3601,7 @@ int hci_write_fast_connectable_sync(struct hci_dev *hdev, bool enable) } static bool disconnected_accept_list_entries(struct hci_dev *hdev) + __must_hold(&hdev->lock) { struct bdaddr_list *b; @@ -3610,12 +3642,16 @@ int hci_update_scan_sync(struct hci_dev *hdev) if (hdev->scanning_paused) return 0; + hci_dev_lock(hdev); + if (hci_dev_test_flag(hdev, HCI_CONNECTABLE) || disconnected_accept_list_entries(hdev)) scan = SCAN_PAGE; else scan = SCAN_DISABLED; + hci_dev_unlock(hdev); + if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) scan |= SCAN_INQUIRY; -- 2.53.0