| From 8d9d0df81c1a5dbb91a04da6e7a3202650c85db3 Mon Sep 17 00:00:00 2001 |
| From: csonsino <csonsino@gmail.com> |
| Date: Wed, 12 Jun 2019 15:00:52 -0600 |
| Subject: Bluetooth: validate BLE connection interval updates |
| |
| [ Upstream commit c49a8682fc5d298d44e8d911f4fa14690ea9485e ] |
| |
| Problem: The Linux Bluetooth stack yields complete control over the BLE |
| connection interval to the remote device. |
| |
| The Linux Bluetooth stack provides access to the BLE connection interval |
| min and max values through /sys/kernel/debug/bluetooth/hci0/ |
| conn_min_interval and /sys/kernel/debug/bluetooth/hci0/conn_max_interval. |
| These values are used for initial BLE connections, but the remote device |
| has the ability to request a connection parameter update. In the event |
| that the remote side requests to change the connection interval, the Linux |
| kernel currently only validates that the desired value is within the |
| acceptable range in the Bluetooth specification (6 - 3200, corresponding to |
| 7.5ms - 4000ms). There is currently no validation that the desired value |
| requested by the remote device is within the min/max limits specified in |
| the conn_min_interval/conn_max_interval configurations. This essentially |
| leads to Linux yielding complete control over the connection interval to |
| the remote device. |
| |
| The proposed patch adds a verification step to the connection parameter |
| update mechanism, ensuring that the desired value is within the min/max |
| bounds of the current connection. If the desired value is outside of the |
| current connection min/max values, then the connection parameter update |
| request is rejected and the negative response is returned to the remote |
| device. Recall that the initial connection is established using the local |
| conn_min_interval/conn_max_interval values, so this allows the Linux |
| administrator to retain control over the BLE connection interval. |
| |
| The one downside that I see is that the current default Linux values for |
| conn_min_interval and conn_max_interval typically correspond to 30ms and |
| 50ms respectively. If this change were accepted, then it is feasible that |
| some devices would no longer be able to negotiate to their desired |
| connection interval values. This might be remedied by setting the default |
| Linux conn_min_interval and conn_max_interval values to the widest |
| supported range (6 - 3200 / 7.5ms - 4000ms). This could lead to the same |
| behavior as the current implementation, where the remote device could |
| request to change the connection interval value to any value that is |
| permitted by the Bluetooth specification, and Linux would accept the |
| desired value. |
| |
| Signed-off-by: Carey Sonsino <csonsino@gmail.com> |
| Signed-off-by: Marcel Holtmann <marcel@holtmann.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/bluetooth/hci_event.c | 5 +++++ |
| net/bluetooth/l2cap_core.c | 9 ++++++++- |
| 2 files changed, 13 insertions(+), 1 deletion(-) |
| |
| diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c |
| index 363dc85bbc5c..3d2f64a6d623 100644 |
| --- a/net/bluetooth/hci_event.c |
| +++ b/net/bluetooth/hci_event.c |
| @@ -5089,6 +5089,11 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, |
| return send_conn_param_neg_reply(hdev, handle, |
| HCI_ERROR_UNKNOWN_CONN_ID); |
| |
| + if (min < hcon->le_conn_min_interval || |
| + max > hcon->le_conn_max_interval) |
| + return send_conn_param_neg_reply(hdev, handle, |
| + HCI_ERROR_INVALID_LL_PARAMS); |
| + |
| if (hci_check_conn_params(min, max, latency, timeout)) |
| return send_conn_param_neg_reply(hdev, handle, |
| HCI_ERROR_INVALID_LL_PARAMS); |
| diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c |
| index 0c2219f483d7..4dc1db85a9c2 100644 |
| --- a/net/bluetooth/l2cap_core.c |
| +++ b/net/bluetooth/l2cap_core.c |
| @@ -5287,7 +5287,14 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, |
| |
| memset(&rsp, 0, sizeof(rsp)); |
| |
| - err = hci_check_conn_params(min, max, latency, to_multiplier); |
| + if (min < hcon->le_conn_min_interval || |
| + max > hcon->le_conn_max_interval) { |
| + BT_DBG("requested connection interval exceeds current bounds."); |
| + err = -EINVAL; |
| + } else { |
| + err = hci_check_conn_params(min, max, latency, to_multiplier); |
| + } |
| + |
| if (err) |
| rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); |
| else |
| -- |
| 2.20.1 |
| |