]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Bluetooth: Fix Set Extended (Scan Response) Data
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 9 Jun 2021 18:09:27 +0000 (11:09 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Jul 2021 15:00:05 +0000 (17:00 +0200)
[ Upstream commit c9ed0a7077306f9d41d74fb006ab5dbada8349c5 ]

These command do have variable length and the length can go up to 251,
so this changes the struct to not use a fixed size and then when
creating the PDU only the actual length of the data send to the
controller.

Fixes: a0fb3726ba551 ("Bluetooth: Use Set ext adv/scan rsp data if controller supports")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_request.c

index ba2f439bc04d346ae5c738b48093e6d8873248ae..46d99c2778c3eca449bc61fb9158241c1869a7b7 100644 (file)
@@ -1773,13 +1773,15 @@ struct hci_cp_ext_adv_set {
        __u8  max_events;
 } __packed;
 
+#define HCI_MAX_EXT_AD_LENGTH  251
+
 #define HCI_OP_LE_SET_EXT_ADV_DATA             0x2037
 struct hci_cp_le_set_ext_adv_data {
        __u8  handle;
        __u8  operation;
        __u8  frag_pref;
        __u8  length;
-       __u8  data[HCI_MAX_AD_LENGTH];
+       __u8  data[];
 } __packed;
 
 #define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA                0x2038
@@ -1788,7 +1790,7 @@ struct hci_cp_le_set_ext_scan_rsp_data {
        __u8  operation;
        __u8  frag_pref;
        __u8  length;
-       __u8  data[HCI_MAX_AD_LENGTH];
+       __u8  data[];
 } __packed;
 
 #define LE_SET_ADV_DATA_OP_COMPLETE    0x03
index ca4ac6603b9a0fd8859cf7eb6c19b3dc45872560..8674141337b73d091e0353bfea3644fbbefdd47b 100644 (file)
@@ -228,9 +228,9 @@ struct adv_info {
        __u16   remaining_time;
        __u16   duration;
        __u16   adv_data_len;
-       __u8    adv_data[HCI_MAX_AD_LENGTH];
+       __u8    adv_data[HCI_MAX_EXT_AD_LENGTH];
        __u16   scan_rsp_len;
-       __u8    scan_rsp_data[HCI_MAX_AD_LENGTH];
+       __u8    scan_rsp_data[HCI_MAX_EXT_AD_LENGTH];
        __s8    tx_power;
        __u32   min_interval;
        __u32   max_interval;
@@ -550,9 +550,9 @@ struct hci_dev {
        DECLARE_BITMAP(dev_flags, __HCI_NUM_FLAGS);
 
        __s8                    adv_tx_power;
-       __u8                    adv_data[HCI_MAX_AD_LENGTH];
+       __u8                    adv_data[HCI_MAX_EXT_AD_LENGTH];
        __u8                    adv_data_len;
-       __u8                    scan_rsp_data[HCI_MAX_AD_LENGTH];
+       __u8                    scan_rsp_data[HCI_MAX_EXT_AD_LENGTH];
        __u8                    scan_rsp_data_len;
 
        struct list_head        adv_instances;
index 805ce546b8133d5f102d75602ea9a52f1d98f08c..e5d6b1d127645e5b03e3b9f0f0f3db4e71993d13 100644 (file)
@@ -1685,30 +1685,33 @@ void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
                return;
 
        if (ext_adv_capable(hdev)) {
-               struct hci_cp_le_set_ext_scan_rsp_data cp;
+               struct {
+                       struct hci_cp_le_set_ext_scan_rsp_data cp;
+                       u8 data[HCI_MAX_EXT_AD_LENGTH];
+               } pdu;
 
-               memset(&cp, 0, sizeof(cp));
+               memset(&pdu, 0, sizeof(pdu));
 
                if (instance)
                        len = create_instance_scan_rsp_data(hdev, instance,
-                                                           cp.data);
+                                                           pdu.data);
                else
-                       len = create_default_scan_rsp_data(hdev, cp.data);
+                       len = create_default_scan_rsp_data(hdev, pdu.data);
 
                if (hdev->scan_rsp_data_len == len &&
-                   !memcmp(cp.data, hdev->scan_rsp_data, len))
+                   !memcmp(pdu.data, hdev->scan_rsp_data, len))
                        return;
 
-               memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
+               memcpy(hdev->scan_rsp_data, pdu.data, len);
                hdev->scan_rsp_data_len = len;
 
-               cp.handle = instance;
-               cp.length = len;
-               cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
-               cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
+               pdu.cp.handle = instance;
+               pdu.cp.length = len;
+               pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
+               pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
 
-               hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, sizeof(cp),
-                           &cp);
+               hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA,
+                           sizeof(pdu.cp) + len, &pdu.cp);
        } else {
                struct hci_cp_le_set_scan_rsp_data cp;
 
@@ -1831,26 +1834,30 @@ void __hci_req_update_adv_data(struct hci_request *req, u8 instance)
                return;
 
        if (ext_adv_capable(hdev)) {
-               struct hci_cp_le_set_ext_adv_data cp;
+               struct {
+                       struct hci_cp_le_set_ext_adv_data cp;
+                       u8 data[HCI_MAX_EXT_AD_LENGTH];
+               } pdu;
 
-               memset(&cp, 0, sizeof(cp));
+               memset(&pdu, 0, sizeof(pdu));
 
-               len = create_instance_adv_data(hdev, instance, cp.data);
+               len = create_instance_adv_data(hdev, instance, pdu.data);
 
                /* There's nothing to do if the data hasn't changed */
                if (hdev->adv_data_len == len &&
-                   memcmp(cp.data, hdev->adv_data, len) == 0)
+                   memcmp(pdu.data, hdev->adv_data, len) == 0)
                        return;
 
-               memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
+               memcpy(hdev->adv_data, pdu.data, len);
                hdev->adv_data_len = len;
 
-               cp.length = len;
-               cp.handle = instance;
-               cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
-               cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
+               pdu.cp.length = len;
+               pdu.cp.handle = instance;
+               pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
+               pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
 
-               hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(cp), &cp);
+               hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA,
+                           sizeof(pdu.cp) + len, &pdu.cp);
        } else {
                struct hci_cp_le_set_adv_data cp;