summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-at91-5.4.199/linux-5.4-bluetooth-connections.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/linux-at91-5.4.199/linux-5.4-bluetooth-connections.patch')
-rw-r--r--recipes-kernel/linux/linux-at91-5.4.199/linux-5.4-bluetooth-connections.patch161
1 files changed, 161 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-at91-5.4.199/linux-5.4-bluetooth-connections.patch b/recipes-kernel/linux/linux-at91-5.4.199/linux-5.4-bluetooth-connections.patch
new file mode 100644
index 0000000..2ffaf4f
--- /dev/null
+++ b/recipes-kernel/linux/linux-at91-5.4.199/linux-5.4-bluetooth-connections.patch
@@ -0,0 +1,161 @@
+This patch updated for the 5.4.199 kernel on Friday, 24 June 2022 by
+John Klug <john.klug@multitech.com>
+
+From d5ebaa7c5f6f688959e8d40840b2249ede63b8ed Mon Sep 17 00:00:00 2001
+From: Soenke Huster <soenke.huster@eknoes.de>
+Date: Sun, 23 Jan 2022 15:06:24 +0100
+Subject: Bluetooth: hci_event: Ignore multiple conn complete events
+
+When one of the three connection complete events is received multiple
+times for the same handle, the device is registered multiple times which
+leads to memory corruptions. Therefore, consequent events for a single
+connection are ignored.
+
+The conn->state can hold different values, therefore HCI_CONN_HANDLE_UNSET
+is introduced to identify new connections. To make sure the events do not
+contain this or another invalid handle HCI_CONN_HANDLE_MAX and checks
+are introduced.
+
+Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=215497
+Signed-off-by: Soenke Huster <soenke.huster@eknoes.de>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+---
+ include/net/bluetooth/hci_core.h | 3 ++
+ net/bluetooth/hci_conn.c | 1 +
+ net/bluetooth/hci_event.c | 63 ++++++++++++++++++++++++++++++----------
+ 3 files changed, 52 insertions(+), 15 deletions(-)
+
+diff -Naru a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+--- a/include/net/bluetooth/hci_core.h 2022-06-24 09:07:33.521766338 -0500
++++ b/include/net/bluetooth/hci_core.h 2022-06-24 09:16:20.317754010 -0500
+@@ -193,6 +193,9 @@
+
+ #define HCI_MAX_SHORT_NAME_LENGTH 10
+
++#define HCI_CONN_HANDLE_UNSET 0xffff
++#define HCI_CONN_HANDLE_MAX 0x0eff
++
+ /* Min encryption key size to match with SMP */
+ #define HCI_MIN_ENC_KEY_SIZE 7
+
+diff -Naru a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+--- a/net/bluetooth/hci_conn.c 2022-06-24 09:08:47.105764616 -0500
++++ b/net/bluetooth/hci_conn.c 2022-06-24 09:16:20.317754010 -0500
+@@ -504,6 +504,7 @@
+
+ bacpy(&conn->dst, dst);
+ bacpy(&conn->src, &hdev->bdaddr);
++ conn->handle = HCI_CONN_HANDLE_UNSET;
+ conn->hdev = hdev;
+ conn->type = type;
+ conn->role = role;
+diff -Naru a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+--- a/net/bluetooth/hci_event.c 2022-06-24 09:09:10.825764061 -0500
++++ b/net/bluetooth/hci_event.c 2022-06-24 09:19:52.017749056 -0500
+@@ -2494,6 +2494,11 @@
+ struct hci_ev_conn_complete *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
++ if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
++ BT_DBG("Ignoring HCI_Connection_Complete for invalid handle");
++ return;
++ }
++
+ BT_DBG("%s", hdev->name);
+
+ hci_dev_lock(hdev);
+@@ -2510,6 +2515,17 @@
+ conn->type = SCO_LINK;
+ }
+
++ /* The HCI_Connection_Complete event is only sent once per connection.
++ * Processing it more than once per connection can corrupt kernel memory.
++ *
++ * As the connection handle is set here for the first time, it indicates
++ * whether the connection is already set up.
++ */
++ if (conn->handle != HCI_CONN_HANDLE_UNSET) {
++ BT_DBG("Ignoring HCI_Connection_Complete for existing connection");
++ goto unlock;
++ }
++
+ if (!ev->status) {
+ conn->handle = __le16_to_cpu(ev->handle);
+
+@@ -4177,6 +4193,11 @@
+ struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
+ struct hci_conn *conn;
+
++ if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
++ BT_DBG("Ignoring HCI_Sync_Conn_Complete event for invalid handle");
++ return;
++ }
++
+ BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+@@ -4200,23 +4221,19 @@
+ goto unlock;
+ }
+
++ /* The HCI_Synchronous_Connection_Complete event is only sent once per connection.
++ * Processing it more than once per connection can corrupt kernel memory.
++ *
++ * As the connection handle is set here for the first time, it indicates
++ * whether the connection is already set up.
++ */
++ if (conn->handle != HCI_CONN_HANDLE_UNSET) {
++ BT_DBG("Ignoring HCI_Sync_Conn_Complete event for existing connection");
++ goto unlock;
++ }
++
+ switch (ev->status) {
+ case 0x00:
+- /* The synchronous connection complete event should only be
+- * sent once per new connection. Receiving a successful
+- * complete event when the connection status is already
+- * BT_CONNECTED means that the device is misbehaving and sent
+- * multiple complete event packets for the same new connection.
+- *
+- * Registering the device more than once can corrupt kernel
+- * memory, hence upon detecting this invalid event, we report
+- * an error and ignore the packet.
+- */
+- if (conn->state == BT_CONNECTED) {
+- bt_dev_err(hdev, "Ignoring connect complete event for existing connection");
+- goto unlock;
+- }
+-
+ conn->handle = __le16_to_cpu(ev->handle);
+ conn->state = BT_CONNECTED;
+ conn->type = ev->link_type;
+@@ -4985,6 +5002,11 @@
+ struct smp_irk *irk;
+ u8 addr_type;
+
++ if (handle > HCI_CONN_HANDLE_MAX) {
++ BT_DBG("Ignoring HCI_LE_Connection_Complete for invalid handle");
++ return;
++ }
++
+ hci_dev_lock(hdev);
+
+ /* All controllers implicitly stop advertising in the event of a
+@@ -5026,6 +5048,17 @@
+ cancel_delayed_work(&conn->le_conn_timeout);
+ }
+
++ /* The HCI_LE_Connection_Complete event is only sent once per connection.
++ * Processing it more than once per connection can corrupt kernel memory.
++ *
++ * As the connection handle is set here for the first time, it indicates
++ * whether the connection is already set up.
++ */
++ if (conn->handle != HCI_CONN_HANDLE_UNSET) {
++ BT_DBG("Ignoring HCI_Connection_Complete for existing connection");
++ goto unlock;
++ }
++
+ le_conn_update_addr(conn, bdaddr, bdaddr_type, local_rpa);
+
+ /* Lookup the identity address from the stored connection