Security
Headlines
HeadlinesLatestCVEs

Headline

CVE-2023-5753: Buffer overflow vulnerabilities in the Zephyr Bluetooth subsystem

Potential buffer overflows in the Bluetooth subsystem due to asserts being disabled in /subsys/bluetooth/host/hci_core.c

CVE
#vulnerability#dos#git#buffer_overflow

Summary

I spotted some additional buffer overflow vulnerabilities at the following locations in the Zephyr Bluetooth subsystem source code:
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/controller/ll_sw/ull_adv.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/host/hci_core.c
https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/bluetooth/host/iso.c

Details

Potential integer underflow due to ineffective assert check leading to buffer overflow in /subsys/bluetooth/controller/ll_sw/ull_adv.c:

uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type, uint8_t own_addr_type, uint8_t direct_addr_type, uint8_t const *const direct_addr, uint8_t chan_map, uint8_t filter_policy) { … #if defined(CONFIG_BT_CTLR_AD_DATA_BACKUP) /* Backup the legacy AD Data if switching to legacy directed advertising * or to Extended Advertising. */ if (((pdu->type == PDU_ADV_TYPE_DIRECT_IND) || (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) && (pdu->type == PDU_ADV_TYPE_EXT_IND))) && (pdu_type_prev != PDU_ADV_TYPE_DIRECT_IND) && (!IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) || (pdu_type_prev != PDU_ADV_TYPE_EXT_IND))) { if (pdu->len == 0U) { adv->ad_data_backup.len = 0U; } else { LL_ASSERT(pdu->len >= offsetof(struct pdu_adv_adv_ind, data)); /* VULN: assert */

        adv\->ad\_data\_backup.len \= pdu\->len \-
            offsetof(struct pdu\_adv\_adv\_ind, data); /\* VULN: integer underflow \*/
        memcpy(adv\->ad\_data\_backup.data, pdu\->adv\_ind.data,
               adv\->ad\_data\_backup.len); /\* VULN: buffer overflow \*/
    }
}

#endif /* CONFIG_BT_CTLR_AD_DATA_BACKUP */ …

Buffer overflows due to assert in /subsys/bluetooth/host/hci_core.c:

#if defined(CONFIG_BT_CONN) static void hci_acl(struct net_buf *buf) { struct bt_hci_acl_hdr *hdr; uint16_t handle, len; struct bt_conn *conn; uint8_t flags;

LOG\_DBG("buf %p", buf);

BT\_ASSERT(buf\->len >= sizeof(\*hdr)); /\* VULN: assert \*/

hdr \= net\_buf\_pull\_mem(buf, sizeof(\*hdr)); /\* VULN: buffer overflow \*/
len \= sys\_le16\_to\_cpu(hdr\->len);
handle \= sys\_le16\_to\_cpu(hdr\->handle);
flags \= bt\_acl\_flags(handle);

static void hci_event(struct net_buf *buf) { struct bt_hci_evt_hdr *hdr;

BT\_ASSERT(buf\->len >= sizeof(\*hdr)); /\* VULN: assert \*/

hdr \= net\_buf\_pull\_mem(buf, sizeof(\*hdr)); /\* VULN: buffer overflow \*/
LOG\_DBG("event 0x%02x", hdr\->evt);
BT\_ASSERT(bt\_hci\_evt\_get\_flags(hdr\->evt) & BT\_HCI\_EVT\_FLAG\_RECV); 

handle\_event(hdr\->evt, buf, normal\_events, ARRAY\_SIZE(normal\_events));

net\_buf\_unref(buf);

} …

void hci_event_prio(struct net_buf *buf) { struct net_buf_simple_state state; struct bt_hci_evt_hdr *hdr; uint8_t evt_flags;

net\_buf\_simple\_save(&buf\->b, &state);

BT\_ASSERT(buf\->len >= sizeof(\*hdr)); /\* VULN: assert \*/

hdr \= net\_buf\_pull\_mem(buf, sizeof(\*hdr)); /\* VULN: buffer overflow \*/
evt\_flags \= bt\_hci\_evt\_get\_flags(hdr\->evt);
BT\_ASSERT(evt\_flags & BT\_HCI\_EVT\_FLAG\_RECV\_PRIO);

handle\_event(hdr\->evt, buf, prio\_events, ARRAY\_SIZE(prio\_events));

if (evt\_flags & BT\_HCI\_EVT\_FLAG\_RECV) {
    net\_buf\_simple\_restore(&buf\->b, &state);
} else {
    net\_buf\_unref(buf);
}

}

Buffer overflow due to assert in /subsys/bluetooth/host/iso.c:

void hci_iso(struct net_buf *buf) { struct bt_hci_iso_hdr *hdr; uint16_t handle, len; struct bt_conn *iso; uint8_t flags;

BT\_ISO\_DATA\_DBG("buf %p", buf);

BT\_ASSERT(buf\->len >= sizeof(\*hdr)); /\* VULN: assert \*/

hdr \= net\_buf\_pull\_mem(buf, sizeof(\*hdr)); /\* VULN: buffer overflow \*/
len \= bt\_iso\_hdr\_len(sys\_le16\_to\_cpu(hdr\->len));
handle \= sys\_le16\_to\_cpu(hdr\->handle);
flags \= bt\_iso\_flags(handle);

In addition, the following helper functions in /subsys/net/buf_simple.c use assertions to check input, which renders checks ineffective:

  • net_buf_simple_add()
  • net_buf_simple_remove_mem()
  • net_buf_simple_push()
  • net_buf_simple_pull()
  • net_buf_simple_pull_mem()

PoC

I haven’t tried to reproduce these potential vulnerabilities against a live install of the Zephyr OS.

Impact

If the unchecked input above is attacker-controlled and crosses a security boundary, the impact of buffer overflow vulnerabilities could range from denial of service to arbitrary code execution.

Patches

This has been fixed in:

  • main for 3.5: #63605

Note that the first item in this advisory, the one involving /subsys/bluetooth/controller/ll_sw/ull_adv.c, has not been addressed because the pdu length that is being asserted on has been set by the controller itself prior to the execution of this code, and so it is not coming from the outside world. Hence, an assertion is correct in that particular case.

For more information

If you have any questions or comments about this advisory:

  • Open an issue in zephyr
  • Email us at Zephyr-vulnerabilities

Related news

Zephyr RTOS 3.x.0 Buffer Overflows

Zephyr RTOS versions 3.5.0 and below suffer from a multitude of buffer overflow vulnerabilities.

CVE: Latest News

CVE-2023-50976: Transactions API Authorization by oleiman · Pull Request #14969 · redpanda-data/redpanda
CVE-2023-6905
CVE-2023-6903
CVE-2023-6904
CVE-2023-3907