From b13a27ec5d8d1aff0c4e367e4f9e88f65f11ddc0 Mon Sep 17 00:00:00 2001 From: Sungwoo Kim Date: Wed, 20 Mar 2024 17:56:49 -0400 Subject: [PATCH] Bluetooth: Host: Add a validation for `hci_le_read_max_data_len()` Check max_tx_octects and max_tx_time are in the valid range, according to the BT Core spec 5.4 [Vol 4, Part E, 7.8.46] Fix #70472 Signed-off-by: Sungwoo Kim --- include/zephyr/bluetooth/hci_types.h | 11 +++++++++++ subsys/bluetooth/host/hci_core.c | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index f4a731d12386487..98ab1db71901474 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -1272,6 +1272,17 @@ struct bt_hci_cp_le_set_rpa_timeout { uint16_t rpa_timeout; } __packed; +/* All limits according to BT Core spec 5.4 [Vol 4, Part E, 7.8.46] */ +#define BT_HCI_LE_MAX_TX_OCTETS_MIN 0x001B +#define BT_HCI_LE_MAX_TX_OCTETS_MAX 0x00FB +#define BT_HCI_LE_MAX_RX_OCTETS_MIN 0x001B +#define BT_HCI_LE_MAX_RX_OCTETS_MAX 0x00FB + +#define BT_HCI_LE_MAX_TX_TIME_MIN 0x0148 +#define BT_HCI_LE_MAX_TX_TIME_MAX 0x4290 +#define BT_HCI_LE_MAX_RX_TIME_MIN 0x0148 +#define BT_HCI_LE_MAX_RX_TIME_MAX 0x4290 + #define BT_HCI_OP_LE_READ_MAX_DATA_LEN BT_OP(BT_OGF_LE, 0x002f) /* 0x202f */ struct bt_hci_rp_le_read_max_data_len { uint8_t status; diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 2138b8ff2f2116b..7b0bce8bb851b2e 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -407,6 +407,15 @@ static int hci_le_read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) *tx_time = sys_le16_to_cpu(rp->max_tx_time); net_buf_unref(rsp); + if (*tx_octets < BT_HCI_LE_MAX_TX_OCTETS_MIN || + *tx_octets > BT_HCI_LE_MAX_TX_OCTETS_MAX) { + LOG_WRN("tx_octets exceeds the valid range %u", *tx_octets); + } + if (*tx_time < BT_HCI_LE_MAX_TX_TIME_MIN || + *tx_time > BT_HCI_LE_MAX_TX_TIME_MAX) { + LOG_WRN("tx_time exceeds the valid range %u", *tx_time); + } + return 0; } @@ -1682,6 +1691,23 @@ static void le_data_len_change(struct net_buf *buf) uint16_t max_tx_time = sys_le16_to_cpu(evt->max_tx_time); uint16_t max_rx_time = sys_le16_to_cpu(evt->max_rx_time); + if (max_tx_octets < BT_HCI_LE_MAX_TX_OCTETS_MIN || + max_tx_octets > BT_HCI_LE_MAX_TX_OCTETS_MAX) { + LOG_WRN("max_tx_octets exceeds the valid range %u", max_tx_octets); + } + if (max_rx_octets < BT_HCI_LE_MAX_RX_OCTETS_MIN || + max_rx_octets > BT_HCI_LE_MAX_RX_OCTETS_MAX) { + LOG_WRN("max_rx_octets exceeds the valid range %u", max_rx_octets); + } + if (max_tx_time < BT_HCI_LE_MAX_TX_TIME_MIN || + max_tx_time > BT_HCI_LE_MAX_TX_TIME_MAX) { + LOG_WRN("max_tx_time exceeds the valid range %u", max_tx_time); + } + if (max_rx_time < BT_HCI_LE_MAX_RX_TIME_MIN || + max_rx_time > BT_HCI_LE_MAX_RX_TIME_MAX) { + LOG_WRN("max_rx_time exceeds the valid range %u", max_rx_time); + } + LOG_DBG("max. tx: %u (%uus), max. rx: %u (%uus)", max_tx_octets, max_tx_time, max_rx_octets, max_rx_time);