[PATCH v2 1/8] Bluetooth: hci_event: extend hdev lock in hci_le_remote_conn_param_req_evt

Pauli Virtanen
2025-11-02T16:23:05Z

Cover conn lookup and field access with hdev lock in
hci_le_remote_conn_param_req_evt.

This avoids any concurrent deletion of the conn before we are done
dereferencing it.

Fixes: 95118dd4edfec ("Bluetooth: hci_event: Use of a function table to handle LE subevents")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
---

Notes:
v2:
- no change

net/bluetooth/hci_event.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ba0a7b41611f..54f757017f3f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6675,25 +6675,31 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, void *data,
latency = le16_to_cpu(ev->latency);
timeout = le16_to_cpu(ev->timeout);

+ hci_dev_lock(hdev);
+
hcon = hci_conn_hash_lookup_handle(hdev, handle);
- if (!hcon || hcon->state != BT_CONNECTED)
- return send_conn_param_neg_reply(hdev, handle,
- HCI_ERROR_UNKNOWN_CONN_ID);
+ if (!hcon || hcon->state != BT_CONNECTED) {
+ send_conn_param_neg_reply(hdev, handle,
+ HCI_ERROR_UNKNOWN_CONN_ID);
+ goto unlock;
+ }

- if (max > hcon->le_conn_max_interval)
- return send_conn_param_neg_reply(hdev, handle,
- HCI_ERROR_INVALID_LL_PARAMS);
+ if (max > hcon->le_conn_max_interval) {
+ send_conn_param_neg_reply(hdev, handle,
+ HCI_ERROR_INVALID_LL_PARAMS);
+ goto unlock;
+ }

- if (hci_check_conn_params(min, max, latency, timeout))
- return send_conn_param_neg_reply(hdev, handle,
- HCI_ERROR_INVALID_LL_PARAMS);
+ if (hci_check_conn_params(min, max, latency, timeout)) {
+ send_conn_param_neg_reply(hdev, handle,
+ HCI_ERROR_INVALID_LL_PARAMS);
+ goto unlock;
+ }

if (hcon->role == HCI_ROLE_MASTER) {
struct hci_conn_params *params;
u8 store_hint;

- hci_dev_lock(hdev);
-
params = hci_conn_params_lookup(hdev, &hcon->dst,
hcon->dst_type);
if (params) {
@@ -6706,8 +6712,6 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, void *data,
store_hint = 0x00;
}

- hci_dev_unlock(hdev);
-
mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
store_hint, min, max, latency, timeout);
}
@@ -6721,6 +6725,9 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, void *data,
cp.max_ce_len = 0;

hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
+
+unlock:
+ hci_dev_unlock(hdev);
}

static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
--
2.51.1