summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeenan Dong <keenanat2000@gmail.com>2026-04-01 22:25:26 +0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2026-04-01 16:47:19 -0400
commitbda93eec78cdbfe5cda00785cefebd443e56b88b (patch)
treeaa07f6bc7a3c7f74398edf881ff3b862a2d07a18
parentb255531b27da336571411248c2a72a350662bd09 (diff)
Bluetooth: MGMT: validate mesh send advertising payload length
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>
-rw-r--r--net/bluetooth/mgmt.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index adcd86c15b4e..b05bb380e5f8 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -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));