| From 1f00c46d29486b1167e6dd095bfb4596b21d4714 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 9 Jun 2021 11:09:27 -0700 |
| Subject: Bluetooth: Fix Set Extended (Scan Response) Data |
| |
| From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| |
| [ 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 | 6 ++-- |
| include/net/bluetooth/hci_core.h | 8 ++--- |
| net/bluetooth/hci_request.c | 51 ++++++++++++++++++-------------- |
| 3 files changed, 37 insertions(+), 28 deletions(-) |
| |
| diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h |
| index 6da4b3c5dd55..243de74e118e 100644 |
| --- a/include/net/bluetooth/hci.h |
| +++ b/include/net/bluetooth/hci.h |
| @@ -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 |
| diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h |
| index df611c8b6b59..e534dff2874e 100644 |
| --- a/include/net/bluetooth/hci_core.h |
| +++ b/include/net/bluetooth/hci_core.h |
| @@ -226,9 +226,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; |
| bdaddr_t random_addr; |
| bool rpa_expired; |
| @@ -523,9 +523,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; |
| diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c |
| index 33dc78c24b73..1a94ed2f8a4f 100644 |
| --- a/net/bluetooth/hci_request.c |
| +++ b/net/bluetooth/hci_request.c |
| @@ -1596,30 +1596,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; |
| |
| @@ -1742,26 +1745,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; |
| |
| -- |
| 2.30.2 |
| |