Merge tag 'for-net-2022-02-24' of git://git.kernel.org/pub/scm/linux/kernel/git/bluet...
authorJakub Kicinski <kuba@kernel.org>
Fri, 25 Feb 2022 02:13:30 +0000 (18:13 -0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 25 Feb 2022 02:13:31 +0000 (18:13 -0800)
Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

 - Fix regression with RFCOMM
 - Fix regression with LE devices using Privacy (RPA)
 - Fix regression with LE devices not waiting proper timeout to
   establish connections
 - Fix race in smp

* tag 'for-net-2022-02-24' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: hci_sync: Fix not using conn_timeout
  Bluetooth: hci_sync: Fix hci_update_accept_list_sync
  Bluetooth: assign len after null check
  Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks
  Bluetooth: fix data races in smp_unregister(), smp_del_chan()
  Bluetooth: hci_core: Fix leaking sent_cmd skb
====================

Link: https://lore.kernel.org/r/20220224210838.197787-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/hci_sync.c
net/bluetooth/mgmt_util.c

index 4b3d0b1..a647e5f 100644 (file)
@@ -506,8 +506,7 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
 
                tmp = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
                if (IS_ERR(tmp)) {
-                       kfree_skb(skb);
-                       return tmp;
+                       return skb;
                }
 
                len -= tmp->len;
index 586f69d..e336e9c 100644 (file)
@@ -1489,6 +1489,14 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 /* Extended advertising support */
 #define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV))
 
+/* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 1789:
+ *
+ * C24: Mandatory if the LE Controller supports Connection State and either
+ * LE Feature (LL Privacy) or LE Feature (Extended Advertising) is supported
+ */
+#define use_enhanced_conn_complete(dev) (ll_privacy_capable(dev) || \
+                                        ext_adv_capable(dev))
+
 /* ----- HCI protocols ----- */
 #define HCI_PROTO_DEFER             0x01
 
index 2b7bd36..2882bc7 100644 (file)
@@ -2738,6 +2738,7 @@ void hci_release_dev(struct hci_dev *hdev)
        hci_dev_unlock(hdev);
 
        ida_simple_remove(&hci_index_ida, hdev->id);
+       kfree_skb(hdev->sent_cmd);
        kfree(hdev);
 }
 EXPORT_SYMBOL(hci_release_dev);
index 0feb68f..9ba2a1a 100644 (file)
@@ -1841,6 +1841,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
        struct bdaddr_list *b, *t;
        u8 num_entries = 0;
        bool pend_conn, pend_report;
+       u8 filter_policy;
        int err;
 
        /* Pause advertising if resolving list can be used as controllers are
@@ -1927,6 +1928,8 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
                err = -EINVAL;
 
 done:
+       filter_policy = err ? 0x00 : 0x01;
+
        /* Enable address resolution when LL Privacy is enabled. */
        err = hci_le_set_addr_resolution_enable_sync(hdev, 0x01);
        if (err)
@@ -1937,7 +1940,7 @@ done:
                hci_resume_advertising_sync(hdev);
 
        /* Select filter policy to use accept list */
-       return err ? 0x00 : 0x01;
+       return filter_policy;
 }
 
 /* Returns true if an le connection is in the scanning state */
@@ -3262,10 +3265,10 @@ static int hci_le_set_event_mask_sync(struct hci_dev *hdev)
        if (hdev->le_features[0] & HCI_LE_DATA_LEN_EXT)
                events[0] |= 0x40;      /* LE Data Length Change */
 
-       /* If the controller supports LL Privacy feature, enable
-        * the corresponding event.
+       /* If the controller supports LL Privacy feature or LE Extended Adv,
+        * enable the corresponding event.
         */
-       if (hdev->le_features[0] & HCI_LE_LL_PRIVACY)
+       if (use_enhanced_conn_complete(hdev))
                events[1] |= 0x02;      /* LE Enhanced Connection Complete */
 
        /* If the controller supports Extended Scanner Filter
@@ -4106,9 +4109,9 @@ int hci_dev_close_sync(struct hci_dev *hdev)
        hci_inquiry_cache_flush(hdev);
        hci_pend_le_actions_clear(hdev);
        hci_conn_hash_flush(hdev);
-       hci_dev_unlock(hdev);
-
+       /* Prevent data races on hdev->smp_data or hdev->smp_bredr_data */
        smp_unregister(hdev);
+       hci_dev_unlock(hdev);
 
        hci_sock_dev_event(hdev, HCI_DEV_DOWN);
 
@@ -5185,7 +5188,7 @@ int hci_le_ext_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn,
        return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_EXT_CREATE_CONN,
                                        plen, data,
                                        HCI_EV_LE_ENHANCED_CONN_COMPLETE,
-                                       HCI_CMD_TIMEOUT, NULL);
+                                       conn->conn_timeout, NULL);
 }
 
 int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
@@ -5270,9 +5273,18 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
        cp.min_ce_len = cpu_to_le16(0x0000);
        cp.max_ce_len = cpu_to_le16(0x0000);
 
+       /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 2261:
+        *
+        * If this event is unmasked and the HCI_LE_Connection_Complete event
+        * is unmasked, only the HCI_LE_Enhanced_Connection_Complete event is
+        * sent when a new connection has been created.
+        */
        err = __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_CREATE_CONN,
-                                      sizeof(cp), &cp, HCI_EV_LE_CONN_COMPLETE,
-                                      HCI_CMD_TIMEOUT, NULL);
+                                      sizeof(cp), &cp,
+                                      use_enhanced_conn_complete(hdev) ?
+                                      HCI_EV_LE_ENHANCED_CONN_COMPLETE :
+                                      HCI_EV_LE_CONN_COMPLETE,
+                                      conn->conn_timeout, NULL);
 
 done:
        /* Re-enable advertising after the connection attempt is finished. */
index edee60b..37eef2c 100644 (file)
@@ -77,11 +77,12 @@ int mgmt_send_event_skb(unsigned short channel, struct sk_buff *skb, int flag,
 {
        struct hci_dev *hdev;
        struct mgmt_hdr *hdr;
-       int len = skb->len;
+       int len;
 
        if (!skb)
                return -EINVAL;
 
+       len = skb->len;
        hdev = bt_cb(skb)->mgmt.hdev;
 
        /* Time stamp */