From nobody Sun Jul 26 01:44:31 2026 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (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 B9CDD3EF66A; Fri, 10 Jul 2026 08:24:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671845; cv=pass; b=pA5n3EL+rpfOe86hB8qBxeg81wwTl7rPA5RqyoRwu3VhPwwX4pmTMWqFrS11xAjaVKAqqptREWLwNScDJSsh4iOVL08IjvzbyY96whJPLGDfgIBIqnXotLG++gINXcvkJQ0CFLMO7x/LQ4bg0NDJRjnsyCnkcU8jorFgpb7tN+Q= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671845; c=relaxed/simple; bh=fZ49Q7SeFthw4t896e0k/bg19qfxY9mN58heOC0c61g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iM90VYHvMRcFtqkjALQJPo37UQ85zO8/MlGgaBSuQKpqHhpUXbN2acRyDggve0Rhr/vapajrksWZYmvq2Nj4hKFjao8QND9jT7kXwUABGcUwBiDkdwHj6Y6RuQCHeMgv1c3ZhlpO9uJ2MrNwJWiwrqYRHfzaOLvGIcSgXtYH4R4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=LT49TQZm; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="LT49TQZm" Received: from monolith.lan (unknown [IPv6:2a0c:f040:0:2790::a03d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by meesny.iki.fi (Postfix) with ESMTPSA id 4gxPxR3sxxzybm; Fri, 10 Jul 2026 11:23:55 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671835; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HmK9QaRWo8lr8saImh/i1zoXbZl7bR5ojsH+iQznLAY=; b=LT49TQZmdYbuQCQPDGXr229MnPleUlIKB9VS4MxtwuNboF0XyBgHmDJkzf0MRF/i1ZZeJF zVK5GxISeX2PJ7zuiPsgmBDVamJ9ZlqSY+goV2tfE0g+fd1IM8/XIn0MlCxyE62TbxV9Rd dOR56mdww/umafxqXpRqs0TIhMqRiNM= ARC-Seal: i=1; a=rsa-sha256; d=iki.fi; s=meesny; cv=none; t=1783671835; b=lJub6NFI+BW6uDfwnhy5MWUz70XiWmJ3pcAU3L//mATLuzY6nT5E04orC5T9iJXG7S3zZr FP+c4kLBvH9SIZKjXOWJbOqLAIbOoVc8E6oY3vV1SiEzWM7MUAW0Ycw9PyH4aQtNegXSR5 +tNoVzGrbVSnic0Q4rr/a7guym0J+zI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671835; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HmK9QaRWo8lr8saImh/i1zoXbZl7bR5ojsH+iQznLAY=; b=uSmrfyP4H2BpcfKsgwr/MkQb0Odk39dDNpSA7uqg79R5x3SjGuRSf57j5Z3bTIEdWxoouI /DVtRYx3wHHf6K6u484J02NHMVtlaoGMHqENlcJ8VHtHOS4o8ThZO+Ik+cYTOP7Q2BmQb1 5d4naVC+5eHDi8JuUCAa+Mngp5EarPs= ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen , marcel@holtmann.org, luiz.dentz@gmail.com, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/4] Bluetooth: hci_sync: extend conn_hash lookup critical sections Date: Fri, 10 Jul 2026 11:23:40 +0300 Message-ID: <4853db33fb044122e1eac76736c5cd0529d13349.1783671570.git.pav@iki.fi> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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: 58ddd115fe063 ("Bluetooth: hci_conn: Fix not setting conn_timeout fo= r Broadcast Receiver") Signed-off-by: Pauli Virtanen --- Notes: v3: - no change v2: - take hdev->lock instead of RCU in hci_update_scan_sync() to guard also the hdev->accept_list access 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 b096fca86bb5..5dddeed11372 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -1028,14 +1028,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; } =20 + rcu_read_unlock(); + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_RANDOM_ADDR, 6, rpa, HCI_CMD_TIMEOUT); } @@ -2621,12 +2626,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; } =20 + rcu_read_unlock(); + /* Cannot disable addr resolution if advertising is enabled. */ err =3D hci_pause_advertising_sync(hdev); if (err) { @@ -2764,6 +2774,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; =20 + rcu_read_lock(); + conn =3D hci_conn_hash_lookup_create_pa_sync(hdev); if (conn) { struct conn_params pa; @@ -2773,6 +2785,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev = *hdev) bacpy(&pa.addr, &conn->dst); pa.addr_type =3D conn->dst_type; =20 + rcu_read_unlock(); + /* Clear first since there could be addresses left * behind. */ @@ -2782,6 +2796,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev = *hdev) err =3D hci_le_add_accept_list_sync(hdev, &pa, &num_entries); goto done; + } else { + rcu_read_unlock(); } } =20 @@ -2792,10 +2808,13 @@ static u8 hci_update_accept_list_sync(struct hci_de= v *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; + } =20 - /* Pointers not dereferenced, no locks needed */ pend_conn =3D hci_pend_le_action_lookup(&hdev->pend_le_conns, &b->bdaddr, b->bdaddr_type); @@ -2803,6 +2822,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev = *hdev) &b->bdaddr, b->bdaddr_type); =20 + rcu_read_unlock(); + /* If the device is not likely to connect or report, * remove it from the acceptlist. */ @@ -2929,6 +2950,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_= dev *hdev, u8 type, if (sent) { struct hci_conn *conn; =20 + rcu_read_lock(); + conn =3D hci_conn_hash_lookup_ba(hdev, PA_LINK, &sent->bdaddr); if (conn) { @@ -2953,8 +2976,12 @@ static int hci_le_set_ext_scan_param_sync(struct hci= _dev *hdev, u8 type, phy++; } =20 + rcu_read_unlock(); + if (num_phy) goto done; + } else { + rcu_read_unlock(); } } } @@ -3205,12 +3232,16 @@ int hci_update_passive_scan_sync(struct hci_dev *hd= ev) /* If there is at least one pending LE connection, we should * keep the background scan running. */ + bool exists; =20 /* 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 =3D hci_lookup_le_connect(hdev); + rcu_read_unlock(); + if (exists) return 0; =20 bt_dev_dbg(hdev, "start background scanning"); @@ -3428,6 +3459,7 @@ int hci_write_fast_connectable_sync(struct hci_dev *h= dev, bool enable) } =20 static bool disconnected_accept_list_entries(struct hci_dev *hdev) + __must_hold(&hdev->lock) { struct bdaddr_list *b; =20 @@ -3468,12 +3500,16 @@ int hci_update_scan_sync(struct hci_dev *hdev) if (hdev->scanning_paused) return 0; =20 + hci_dev_lock(hdev); + if (hci_dev_test_flag(hdev, HCI_CONNECTABLE) || disconnected_accept_list_entries(hdev)) scan =3D SCAN_PAGE; else scan =3D SCAN_DISABLED; =20 + hci_dev_unlock(hdev); + if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) scan |=3D SCAN_INQUIRY; =20 --=20 2.55.0 From nobody Sun Jul 26 01:44:31 2026 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (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 6EC1B3EF0C2; Fri, 10 Jul 2026 08:24:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671845; cv=pass; b=eaoe7MiC4y9YFs617LdH+4CBcOKjTYG9paMeb6+mLKsHr8bFKQFow8b5Im+W4gafOxRjTnbxgcJIfkh6GwnmWY2VxFRUCcI+jjBFHj37W52OYPTpErwdhu3GWJjkwHZ/9dxMO+70g6fgTOzijt6pJ6OEXJ9S6EBnkphwHZmWSls= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671845; c=relaxed/simple; bh=PgEsgQfp5WTswf2UXoexyFmK2Cw9h3dNPEUqcjowinU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n+QfEg+C02/44vm1f+xQixj9hGTbi8uWOa4HDnCk/r9rE4VWB9RRkTVfpwogPg1GbcWZzZwRjINv9E0syIHZRpWRbmd15y1ZHgPa8+WwJCujFSgmZLWCNDGthCcyNamzO7dLIZqlEwNfkJdrQ5Rtsot6mVdvBPFp8GNrpX3/ozs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=uTkSzRMH; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="uTkSzRMH" Received: from monolith.lan (unknown [IPv6:2a0c:f040:0:2790::a03d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by meesny.iki.fi (Postfix) with ESMTPSA id 4gxPxS0qXpzyWl; Fri, 10 Jul 2026 11:23:56 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671836; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0oqLO94tAjhpPOZ+UPy92XW9OWXF2NUhjRa5+sh9AcM=; b=uTkSzRMHf9IkxOlG70qmiv9WLdWIr6ibOZbdOuSUZPcfPDHqcHCS96tZIbfjerS3ayNf3/ B+BRHtnW9j/cy8ccnqN7ZBOtYvarQ3J9Q5llE9HR0NofzBqTl3+Sxpf20l/tmi5Lcpu8J5 NlOEq1hofl0GNvAJNM/r+YJMedOgIvc= ARC-Seal: i=1; a=rsa-sha256; d=iki.fi; s=meesny; cv=none; t=1783671836; b=GfSjXzBelU1Ywo/SohlsRezT595Vbzv5id0qwxa3ZeIJ10K5kxsIAFVkCWhRGh9VaLRJmc qJn7qf1xQs9QYlA5Ay3+PwcXgs2vIHyEIGfp/wrr3rWThbAHH4noC3aPeq4iQU1iakXNwN MaWTXl3QDjQ/PHJZ1XS6bFBDTwlS5jE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671836; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0oqLO94tAjhpPOZ+UPy92XW9OWXF2NUhjRa5+sh9AcM=; b=xoitilhqCMlhSy4uHwfzlq9yyvDQKgnLIHdAqx2fTV/6Kzt7yvd3Un+q9yQFSJsJt4G6qI mx0Mt28UFmb3zTY/pCyXGvHP3JSkxF8CDh3oQq41fw3BxU5n3+rxTdF2kJ31cEBw/0hbyD vVaj2y69yTwWDDjFkutFob1CJPv4dO4= ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen , marcel@holtmann.org, luiz.dentz@gmail.com, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/4] Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync Date: Fri, 10 Jul 2026 11:23:41 +0300 Message-ID: <6288c79564bca6dfbf9e4ad87a99247cf7bcff2d.1783671570.git.pav@iki.fi> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Dereferencing RCU-protected pointers outside critical sections is invalid and may lead to UAF. Take hdev->lock for hci_conn lookup and hci_abort_conn(). Don't use RCU to ensure the conn is fully initialized at this point. Fixes: 227a0cdf4a028 ("Bluetooth: MGMT: Fix not generating command complete= for MGMT_OP_DISCONNECT") Signed-off-by: Pauli Virtanen --- Notes: v3: - no change v2: - take hdev->lock instead of RCU, to make sure the conn object is fully initialized before hci_conn_abort_sync() =20 hci_conn_abort_sync() may not be called with hdev->lock held when called from hci_sync workqueue. net/bluetooth/mgmt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 733a4b70e10c..39268f58a49d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3091,6 +3091,8 @@ static int unpair_device_sync(struct hci_dev *hdev, v= oid *data) struct mgmt_cp_unpair_device *cp =3D cmd->param; struct hci_conn *conn; =20 + hci_dev_lock(hdev); + if (cp->addr.type =3D=3D BDADDR_BREDR) conn =3D hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); @@ -3098,6 +3100,11 @@ static int unpair_device_sync(struct hci_dev *hdev, = void *data) conn =3D hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, le_addr_type(cp->addr.type)); =20 + if (conn) + hci_conn_get(conn); + + hci_dev_unlock(hdev); + if (!conn) return 0; =20 @@ -3105,6 +3112,7 @@ static int unpair_device_sync(struct hci_dev *hdev, v= oid *data) * will clean up the connection no matter the error. */ hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); + hci_conn_put(conn); =20 return 0; } @@ -3252,6 +3260,8 @@ static int disconnect_sync(struct hci_dev *hdev, void= *data) struct mgmt_cp_disconnect *cp =3D cmd->param; struct hci_conn *conn; =20 + hci_dev_lock(hdev); + if (cp->addr.type =3D=3D BDADDR_BREDR) conn =3D hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); @@ -3259,6 +3269,11 @@ static int disconnect_sync(struct hci_dev *hdev, voi= d *data) conn =3D hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, le_addr_type(cp->addr.type)); =20 + if (conn) + hci_conn_get(conn); + + hci_dev_unlock(hdev); + if (!conn) return -ENOTCONN; =20 @@ -3266,6 +3281,7 @@ static int disconnect_sync(struct hci_dev *hdev, void= *data) * will clean up the connection no matter the error. */ hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); + hci_conn_put(conn); =20 return 0; } --=20 2.55.0 From nobody Sun Jul 26 01:44:31 2026 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (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 68C673EFFA1; Fri, 10 Jul 2026 08:24:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671846; cv=pass; b=toUdaDGC3xQsvAF1PnMH8vXM07j1gHr321Xm2vWbJddE6kQgarX4YmJgNLYElK7QH/G0rbeE8jyA9dIb0Tgt0BtU3CvvvXZqlQWUfoww4QSG6Cmu5nnKVM2hJW5DegcVVC5PUKlzZAbxtyiwQWlofcb50WRq3a+eGJUghmKT55E= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671846; c=relaxed/simple; bh=g1ImQy1vuGqWTQQgW3En/Th6zW/2Z1D7+gOQwqKiXsM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=V0sW5zTyRBD6No1bycA2InHZ8uupGlU1tNfr1rbVEJDF2TnupId3t7XfDYv4KZWo1CrCWWr5r/Om3po+gnczxgmAlIxlC6B6FtEsJ62QgoJGNrGJBo3Fp4UPBoWChl8XsvqU4FLBkbRYsp7gKUBUWWIVLNz9jQxDAlogiNvOw+k= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=F66VdIMe; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="F66VdIMe" Received: from monolith.lan (unknown [IPv6:2a0c:f040:0:2790::a03d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by meesny.iki.fi (Postfix) with ESMTPSA id 4gxPxS4nPCzyvg; Fri, 10 Jul 2026 11:23:56 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671837; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=884Qbk6aAhZ5jB1/V9NFJtofiSnkEMDDqf2HFjscPaA=; b=F66VdIMeUJMpFrONO4XbTgpuAuDm8rqpcRc9+KlI+9eTtmOAF5HtGV+9W0MCbEMpwGxw50 jyxOeAN7WiICuB2lhJ8C2iqvps3ppi4ueC5LX5I3EWj+B2gVSOLCOfQmujD3N+mgDdftlW jeufg4urDVWiDVhKD3trhEqxlQLCm8A= ARC-Seal: i=1; a=rsa-sha256; d=iki.fi; s=meesny; cv=none; t=1783671837; b=J70qlUpVHJzmg7GOyhbxo58aAye0FNJsAgsaxwx5Hs4AQRav8xVNKmTJYsLKzMl0dJDlTz AUKb2vFCAJtjdzGukBUCWpXCbSDCgmY4MXrQF55hZLTbNBouNUusifHnSgi6WGkL8dE2fJ JTEq+Ar1u0q4IpceSaFD6wOlZZG4NoM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671837; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=884Qbk6aAhZ5jB1/V9NFJtofiSnkEMDDqf2HFjscPaA=; b=jTH+zhikpPqm8yOVcGJj/SVGxys2bLKl9LodKy4U80FGH8JSFmGdNMK0SKD6y8C7w0AY9q D03ERuzLtXP3IiIiPwWUxxDlYkQ1J2FlmUozrNCkTY+N9AO4yeRM0e3YtfogFoQQVqRcfp 6WLLx1TxN31KTmbHzuxEN5EZwOzfaAY= ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen , marcel@holtmann.org, luiz.dentz@gmail.com, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/4] Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds Date: Fri, 10 Jul 2026 11:23:42 +0300 Message-ID: <292363bfecaa083d3a8aa1b5a9f29041cb7eb826.1783671570.git.pav@iki.fi> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Dereferencing RCU-protected pointers outside critical sections is invalid and may lead to UAF. Use of hci_conn in hci_sync callbacks also needs to hold refcount to avoid UAF. Take appropriate locks for hci_conn lookups, and take refcount for hci_conn pointers stored in mgmt_pending_cmd so that the pointer stays valid. When accessing conn->state, ensure hdev->lock is held to avoid data race. Fixes: 7b445e220db9 ("Bluetooth: MGMT: Fix holding hci_conn reference while= command is queued") Signed-off-by: Pauli Virtanen --- Notes: v3: - no change v2: - no change net/bluetooth/mgmt.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 39268f58a49d..c61cb9750872 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -7404,6 +7404,9 @@ static void get_conn_info_complete(struct hci_dev *hd= ev, void *data, int err) rp.max_tx_power =3D HCI_TX_POWER_INVALID; } =20 + if (conn) + hci_conn_put(conn); + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, &rp, sizeof(rp)); =20 @@ -7418,6 +7421,8 @@ static int get_conn_info_sync(struct hci_dev *hdev, v= oid *data) int err; __le16 handle; =20 + hci_dev_lock(hdev); + /* Make sure we are still connected */ if (cp->addr.type =3D=3D BDADDR_BREDR) conn =3D hci_conn_hash_lookup_ba(hdev, ACL_LINK, @@ -7425,12 +7430,16 @@ static int get_conn_info_sync(struct hci_dev *hdev,= void *data) else conn =3D hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); =20 - if (!conn || conn->state !=3D BT_CONNECTED) + if (!conn || conn->state !=3D BT_CONNECTED) { + hci_dev_unlock(hdev); return MGMT_STATUS_NOT_CONNECTED; + } =20 - cmd->user_data =3D conn; + cmd->user_data =3D hci_conn_get(conn); handle =3D cpu_to_le16(conn->handle); =20 + hci_dev_unlock(hdev); + /* Refresh RSSI each time */ err =3D hci_read_rssi_sync(hdev, handle); =20 @@ -7564,6 +7573,9 @@ static void get_clock_info_complete(struct hci_dev *h= dev, void *data, int err) } =20 complete: + if (conn) + hci_conn_put(conn); + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, sizeof(rp)); =20 @@ -7580,15 +7592,21 @@ static int get_clock_info_sync(struct hci_dev *hdev= , void *data) memset(&hci_cp, 0, sizeof(hci_cp)); hci_read_clock_sync(hdev, &hci_cp); =20 + hci_dev_lock(hdev); + /* Make sure connection still exists */ conn =3D hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr); - if (!conn || conn->state !=3D BT_CONNECTED) + if (!conn || conn->state !=3D BT_CONNECTED) { + hci_dev_unlock(hdev); return MGMT_STATUS_NOT_CONNECTED; + } =20 - cmd->user_data =3D conn; + cmd->user_data =3D hci_conn_get(conn); hci_cp.handle =3D cpu_to_le16(conn->handle); hci_cp.which =3D 0x01; /* Piconet clock */ =20 + hci_dev_unlock(hdev); + return hci_read_clock_sync(hdev, &hci_cp); } =20 --=20 2.55.0 From nobody Sun Jul 26 01:44:31 2026 Received: from meesny.iki.fi (meesny.iki.fi [195.140.195.201]) (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 68B5F3EFD24; Fri, 10 Jul 2026 08:24:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=195.140.195.201 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671846; cv=pass; b=eFPryiXONzVBCkg0sGSf1KiItImL7FU/CYGf+EjTh9Q/MBcTrG6L8OwPuT14XwkFnyPkqo85zdiK58HzJcVPE2xunkZ+Lf/7Qzq41stIj1XNBx6dwpHaEkx4O0mFXOMXIR9K1vTJn1WzaWU+NRUNN7QBBuEHIxE9DnCUvXfIwcc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783671846; c=relaxed/simple; bh=qp0LG+dtJvvKhzg73t44YNka2xRXHC8fRZsBriQRA8w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NgMv5hilfUTawjQNiAC07aOTeaxdf9aoNthIdhm49CE5C7WrYGx2cwZaQg0J2sR2yZpu6T67vsyNUTfXfz+8gviT7D11n+JovAePBDG9o9CXknla+JWJdq3YnGYosbJZuoqeCz9kTP4emEd4PUK9AhlZKwfdEthVoZf8TlmPclQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi; spf=pass smtp.mailfrom=iki.fi; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b=P+NYFwok; arc=pass smtp.client-ip=195.140.195.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iki.fi Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iki.fi Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iki.fi header.i=@iki.fi header.b="P+NYFwok" Received: from monolith.lan (unknown [IPv6:2a0c:f040:0:2790::a03d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: pav) by meesny.iki.fi (Postfix) with ESMTPSA id 4gxPxT1fPhzytg; Fri, 10 Jul 2026 11:23:57 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671837; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=b1VEWul+HyxrXWU8hZyHnEDDT4MJtjTgusKZVWDnfrQ=; b=P+NYFwokOwr+orldZ2spD11y3QdgMoCDjwgxK1F4GqhVyJTGbAEBarIMxcNRW28CZ6Hkxv inr6YFmXOljeAgKsfldXqsrtl+Q/UwWjUI5x/Yjdru8s2Z/z7fkYy3cmTc++8lFkQ1ALzD m2bKcWl5vs9xahI7V7KvF3Est5D9Wcw= ARC-Seal: i=1; a=rsa-sha256; d=iki.fi; s=meesny; cv=none; t=1783671837; b=OdFp2CFi4iySuy4L63hpaDAIA/chRAjNqxL5Qs3KX5CchzX57mYoQGcFZsJVmQbbgu9DqL YBM6pJZaGZ6W94xAgjEutACdsvWqmAVPDbWRLljKR9zTalwJyzQ7JAbRTRpUS4h8tuis/S 5HVRJDRzVmyTYv8PkZrO5QtMikwn6Xk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1783671837; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=b1VEWul+HyxrXWU8hZyHnEDDT4MJtjTgusKZVWDnfrQ=; b=y7GC/vOimeCYk0g1vlNnz1o4dA6r928iXs38wBuqb/9ksnLuWxQD5/f1DeUx9ASxTVj9Mq /+5EUkbmARXDz37oMdbCK1sgDlEEhOMOWCVNeQuPnd/Ns1nALWzDTK2smoT5F+pl19lAAt kUkagGf+seWj4o2lJsY0PlgaDbGhec4= ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=pav smtp.mailfrom=pav@iki.fi From: Pauli Virtanen To: linux-bluetooth@vger.kernel.org Cc: Pauli Virtanen , marcel@holtmann.org, luiz.dentz@gmail.com, linux-kernel@vger.kernel.org Subject: [PATCH v3 4/4] Bluetooth: hci_sync: hold hdev->lock for hci_conn_params lookups Date: Fri, 10 Jul 2026 11:23:43 +0300 Message-ID: <50fcbacc691eaffe08a6e3828be372840e1fdf80.1783671570.git.pav@iki.fi> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" hci_conn_params_lookup requires hdev->lock be held, otherwise the list iteration or param access is not safe. Hold hdev->lock for params lookups in hci_sync. Fixes: c530569adc19 ("Bluetooth: hci_core: Introduce HCI_CONN_FLAG_PAST") Signed-off-by: Pauli Virtanen --- Notes: v3: - copy params->flags in hci_le_pa_create_sync() to reduce number of unlocks in branches. Note the lock also protects the `le` hci_conn. v2: - no change net/bluetooth/hci_sync.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 5dddeed11372..b4ca34abe032 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -6677,6 +6677,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hd= ev, void *data) if (!hci_dev_test_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES)) hci_pause_advertising_sync(hdev); =20 + hci_dev_lock(hdev); + params =3D hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); if (params) { conn->le_conn_min_interval =3D params->conn_min_interval; @@ -6690,6 +6692,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hd= ev, void *data) conn->le_supv_timeout =3D hdev->le_supv_timeout; } =20 + hci_dev_unlock(hdev); + /* If controller is scanning, we stop it since some controllers are * not able to scan and connect at the same time. Also set the * HCI_LE_SCAN_INTERRUPTED flag so that the command complete @@ -7247,13 +7251,13 @@ static void create_pa_complete(struct hci_dev *hdev= , void *data, int err) } =20 static int hci_le_past_params_sync(struct hci_dev *hdev, struct hci_conn *= conn, - struct hci_conn *acl, struct bt_iso_qos *qos) + u16 acl_handle, struct bt_iso_qos *qos) { struct hci_cp_le_past_params cp; int err; =20 memset(&cp, 0, sizeof(cp)); - cp.handle =3D cpu_to_le16(acl->handle); + cp.handle =3D cpu_to_le16(acl_handle); /* An HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent * to the Host. HCI_LE_Periodic_Advertising_Report events will be * enabled with duplicate filtering enabled. @@ -7318,16 +7322,28 @@ static int hci_le_pa_create_sync(struct hci_dev *hd= ev, void *data) * 2. Check if that HCI_CONN_FLAG_PAST has been set which indicates that * user really intended to use PAST. */ + hci_dev_lock(hdev); + le =3D hci_conn_hash_lookup_le(hdev, &conn->dst, conn->dst_type); if (le) { struct hci_conn_params *params; + hci_conn_flags_t flags =3D 0; + u16 le_handle =3D le->handle; =20 params =3D hci_conn_params_lookup(hdev, &le->dst, le->dst_type); - if (params && params->flags & HCI_CONN_FLAG_PAST) { - err =3D hci_le_past_params_sync(hdev, conn, le, qos); + if (params) + flags =3D params->flags; + + hci_dev_unlock(hdev); + + if (flags & HCI_CONN_FLAG_PAST) { + err =3D hci_le_past_params_sync(hdev, conn, le_handle, + qos); if (!err) goto done; } + } else { + hci_dev_unlock(hdev); } =20 /* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update --=20 2.55.0