Merge tag 'gpio-fixes-for-v6.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/kernel/linux-rpi.git] / net / bluetooth / hci_event.c
index 31d02b5..1e1c914 100644 (file)
@@ -26,6 +26,8 @@
 /* Bluetooth HCI event handling. */
 
 #include <asm/unaligned.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -3268,6 +3270,16 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
 
        bt_dev_dbg(hdev, "bdaddr %pMR type 0x%x", &ev->bdaddr, ev->link_type);
 
+       /* Reject incoming connection from device with same BD ADDR against
+        * CVE-2020-26555
+        */
+       if (hdev && !bacmp(&hdev->bdaddr, &ev->bdaddr)) {
+               bt_dev_dbg(hdev, "Reject connection with same BD_ADDR %pMR\n",
+                          &ev->bdaddr);
+               hci_reject_conn(hdev, &ev->bdaddr);
+               return;
+       }
+
        mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
                                      &flags);
 
@@ -4742,6 +4754,15 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, void *data,
        if (!conn)
                goto unlock;
 
+       /* Ignore NULL link key against CVE-2020-26555 */
+       if (!crypto_memneq(ev->link_key, ZERO_KEY, HCI_LINK_KEY_SIZE)) {
+               bt_dev_dbg(hdev, "Ignore NULL link key (ZERO KEY) for %pMR",
+                          &ev->bdaddr);
+               hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
+               hci_conn_drop(conn);
+               goto unlock;
+       }
+
        hci_conn_hold(conn);
        conn->disc_timeout = HCI_DISCONN_TIMEOUT;
        hci_conn_drop(conn);
@@ -5274,8 +5295,8 @@ static u8 bredr_oob_data_present(struct hci_conn *conn)
                 * available, then do not declare that OOB data is
                 * present.
                 */
-               if (!memcmp(data->rand256, ZERO_KEY, 16) ||
-                   !memcmp(data->hash256, ZERO_KEY, 16))
+               if (!crypto_memneq(data->rand256, ZERO_KEY, 16) ||
+                   !crypto_memneq(data->hash256, ZERO_KEY, 16))
                        return 0x00;
 
                return 0x02;
@@ -5285,8 +5306,8 @@ static u8 bredr_oob_data_present(struct hci_conn *conn)
         * not supported by the hardware, then check that if
         * P-192 data values are present.
         */
-       if (!memcmp(data->rand192, ZERO_KEY, 16) ||
-           !memcmp(data->hash192, ZERO_KEY, 16))
+       if (!crypto_memneq(data->rand192, ZERO_KEY, 16) ||
+           !crypto_memneq(data->hash192, ZERO_KEY, 16))
                return 0x00;
 
        return 0x01;
@@ -5303,7 +5324,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, void *data,
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-       if (!conn)
+       if (!conn || !hci_conn_ssp_enabled(conn))
                goto unlock;
 
        hci_conn_hold(conn);
@@ -5550,7 +5571,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data,
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-       if (!conn)
+       if (!conn || !hci_conn_ssp_enabled(conn))
                goto unlock;
 
        /* Reset the authentication requirement to unknown */
@@ -7021,6 +7042,14 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+static int hci_iso_term_big_sync(struct hci_dev *hdev, void *data)
+{
+       u8 handle = PTR_UINT(data);
+
+       return hci_le_terminate_big_sync(hdev, handle,
+                                        HCI_ERROR_LOCAL_HOST_TERM);
+}
+
 static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
                                           struct sk_buff *skb)
 {
@@ -7065,16 +7094,17 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
                rcu_read_lock();
        }
 
+       rcu_read_unlock();
+
        if (!ev->status && !i)
                /* If no BISes have been connected for the BIG,
                 * terminate. This is in case all bound connections
                 * have been closed before the BIG creation
                 * has completed.
                 */
-               hci_le_terminate_big_sync(hdev, ev->handle,
-                                         HCI_ERROR_LOCAL_HOST_TERM);
+               hci_cmd_sync_queue(hdev, hci_iso_term_big_sync,
+                                  UINT_PTR(ev->handle), NULL);
 
-       rcu_read_unlock();
        hci_dev_unlock(hdev);
 }