]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: MGMT: validate mesh send advertising payload length
authorKeenan Dong <keenanat2000@gmail.com>
Wed, 1 Apr 2026 14:25:26 +0000 (22:25 +0800)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 1 Apr 2026 20:47:19 +0000 (16:47 -0400)
mesh_send() currently bounds MGMT_OP_MESH_SEND by total command
length, but it never verifies that the bytes supplied for the
flexible adv_data[] array actually match the embedded adv_data_len
field. MGMT_MESH_SEND_SIZE only covers the fixed header, so a
truncated command can still pass the existing 20..50 byte range
check and later drive the async mesh send path past the end of the
queued command buffer.

Keep rejecting zero-length and oversized advertising payloads, but
validate adv_data_len explicitly and require the command length to
exactly match the flexible array size before queueing the request.

Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh")
Reported-by: Keenan Dong <keenanat2000@gmail.com>
Signed-off-by: Keenan Dong <keenanat2000@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/mgmt.c

index adcd86c15b4e634b7f75bb15c4847e57c287089b..b05bb380e5f87715e2a4ac38aa7e7eb77c48549f 100644 (file)
@@ -2478,6 +2478,7 @@ static int mesh_send(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
        struct mgmt_mesh_tx *mesh_tx;
        struct mgmt_cp_mesh_send *send = data;
        struct mgmt_rp_mesh_read_features rp;
+       u16 expected_len;
        bool sending;
        int err = 0;
 
@@ -2485,12 +2486,19 @@ static int mesh_send(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
            !hci_dev_test_flag(hdev, HCI_MESH_EXPERIMENTAL))
                return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
                                       MGMT_STATUS_NOT_SUPPORTED);
-       if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) ||
-           len <= MGMT_MESH_SEND_SIZE ||
-           len > (MGMT_MESH_SEND_SIZE + 31))
+       if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
+               return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
+                                      MGMT_STATUS_REJECTED);
+
+       if (!send->adv_data_len || send->adv_data_len > 31)
                return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
                                       MGMT_STATUS_REJECTED);
 
+       expected_len = struct_size(send, adv_data, send->adv_data_len);
+       if (expected_len != len)
+               return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
+                                      MGMT_STATUS_INVALID_PARAMS);
+
        hci_dev_lock(hdev);
 
        memset(&rp, 0, sizeof(rp));