Skip to content

Commit d5ebaa7

Browse files
eknoesVudentz
authored andcommitted
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>
1 parent 5201d23 commit d5ebaa7

File tree

3 files changed

+52
-15
lines changed

3 files changed

+52
-15
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ struct adv_monitor {
303303

304304
#define HCI_MAX_SHORT_NAME_LENGTH 10
305305

306+
#define HCI_CONN_HANDLE_UNSET 0xffff
307+
#define HCI_CONN_HANDLE_MAX 0x0eff
308+
306309
/* Min encryption key size to match with SMP */
307310
#define HCI_MIN_ENC_KEY_SIZE 7
308311

net/bluetooth/hci_conn.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
689689

690690
bacpy(&conn->dst, dst);
691691
bacpy(&conn->src, &hdev->bdaddr);
692+
conn->handle = HCI_CONN_HANDLE_UNSET;
692693
conn->hdev = hdev;
693694
conn->type = type;
694695
conn->role = role;

net/bluetooth/hci_event.c

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3068,6 +3068,11 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
30683068
struct hci_ev_conn_complete *ev = data;
30693069
struct hci_conn *conn;
30703070

3071+
if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
3072+
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for invalid handle");
3073+
return;
3074+
}
3075+
30713076
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
30723077

30733078
hci_dev_lock(hdev);
@@ -3106,6 +3111,17 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
31063111
}
31073112
}
31083113

3114+
/* The HCI_Connection_Complete event is only sent once per connection.
3115+
* Processing it more than once per connection can corrupt kernel memory.
3116+
*
3117+
* As the connection handle is set here for the first time, it indicates
3118+
* whether the connection is already set up.
3119+
*/
3120+
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
3121+
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
3122+
goto unlock;
3123+
}
3124+
31093125
if (!ev->status) {
31103126
conn->handle = __le16_to_cpu(ev->handle);
31113127

@@ -4674,6 +4690,11 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
46744690
return;
46754691
}
46764692

4693+
if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
4694+
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete for invalid handle");
4695+
return;
4696+
}
4697+
46774698
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
46784699

46794700
hci_dev_lock(hdev);
@@ -4697,23 +4718,19 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
46974718
goto unlock;
46984719
}
46994720

4721+
/* The HCI_Synchronous_Connection_Complete event is only sent once per connection.
4722+
* Processing it more than once per connection can corrupt kernel memory.
4723+
*
4724+
* As the connection handle is set here for the first time, it indicates
4725+
* whether the connection is already set up.
4726+
*/
4727+
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
4728+
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete event for existing connection");
4729+
goto unlock;
4730+
}
4731+
47004732
switch (ev->status) {
47014733
case 0x00:
4702-
/* The synchronous connection complete event should only be
4703-
* sent once per new connection. Receiving a successful
4704-
* complete event when the connection status is already
4705-
* BT_CONNECTED means that the device is misbehaving and sent
4706-
* multiple complete event packets for the same new connection.
4707-
*
4708-
* Registering the device more than once can corrupt kernel
4709-
* memory, hence upon detecting this invalid event, we report
4710-
* an error and ignore the packet.
4711-
*/
4712-
if (conn->state == BT_CONNECTED) {
4713-
bt_dev_err(hdev, "Ignoring connect complete event for existing connection");
4714-
goto unlock;
4715-
}
4716-
47174734
conn->handle = __le16_to_cpu(ev->handle);
47184735
conn->state = BT_CONNECTED;
47194736
conn->type = ev->link_type;
@@ -5509,6 +5526,11 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
55095526
struct smp_irk *irk;
55105527
u8 addr_type;
55115528

5529+
if (handle > HCI_CONN_HANDLE_MAX) {
5530+
bt_dev_err(hdev, "Ignoring HCI_LE_Connection_Complete for invalid handle");
5531+
return;
5532+
}
5533+
55125534
hci_dev_lock(hdev);
55135535

55145536
/* All controllers implicitly stop advertising in the event of a
@@ -5550,6 +5572,17 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
55505572
cancel_delayed_work(&conn->le_conn_timeout);
55515573
}
55525574

5575+
/* The HCI_LE_Connection_Complete event is only sent once per connection.
5576+
* Processing it more than once per connection can corrupt kernel memory.
5577+
*
5578+
* As the connection handle is set here for the first time, it indicates
5579+
* whether the connection is already set up.
5580+
*/
5581+
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
5582+
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
5583+
goto unlock;
5584+
}
5585+
55535586
le_conn_update_addr(conn, bdaddr, bdaddr_type, local_rpa);
55545587

55555588
/* Lookup the identity address from the stored connection

0 commit comments

Comments
 (0)