Headline
Zephyr RTOS 3.x.0 Buffer Overflows
Zephyr RTOS versions 3.5.0 and below suffer from a multitude of buffer overflow vulnerabilities.
–[ HNS-2023-03 - HN Security Advisory - https://security.humanativaspa.it/
- Title: Multiple vulnerabilities in Zephyr RTOS
- OS: Zephyr <= 3.4.0, except for:
- CVE-2023-4265 that affects Zephyr <= 3.3.0
- CVE-2023-4261 that affects Zephyr <= 3.5.0 and will be fixed in a future update
- Author: Marco Ivaldi [email protected]
- Date: 2023-11-07
- CVE IDs and severity:
- CVE-2023-3725 - High - 7.6 - CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H
- CVE-2023-4257 - Moderate - 6.8 - CVSS:3.1/AV:A/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:H
- CVE-2023-4259 - High - 7.1 - CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H
- CVE-2023-4260 - Moderate - 6.3 - CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L
- CVE-2023-4261 - (unreleased)
- CVE-2023-4262 - Moderate - 5.1 - CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L
- CVE-2023-4263 - High - 7.6 - CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H
- CVE-2023-4264 - High - 7.1 - CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L
- CVE-2023-4265 - Moderate - 6.4 - CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H
- CVE-2023-5139 - Moderate - 4.4 - CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L
- CVE-2023-5184 - High - 7.0 - CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:H
- CVE-2023-5753 - Moderate - 6.3 - CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L
- Vendor URL: https://www.zephyrproject.org/
- Advisory URLs:
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-2g3m-p6c7-8rr3
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-853q-q69w-gf5j
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-gghm-c696-f4j4
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-gj27-862r-55wh
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-5954-jcv4-7rvm (unreleased)
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-56p9-5p3v-hhrc
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rf6q-rhhp-pqhf
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rgx6-3w4j-gf5j
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-4vgv-5r6q-r6xh
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rhrc-pcxp-4453
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-8x3p-q3r5-xh9g
- https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-hmpr-px56-rvww
–[ 0 - Table of contents
1 - Summary
2 - Background
3 - Vulnerabilities
3.1 - CVE-2023-3725 - Buffer overflow vulnerability in the Zephyr CANbus subsystem
3.2 - CVE-2023-4257 - Unchecked user input length in the Zephyr WiFi shell module
3.3 - CVE-2023-4259 - Buffer overflow vulnerabilities in the Zephyr eS-WiFi driver
3.4 - CVE-2023-4260 - Off-by-one buffer overflow vulnerability in the Zephyr FS subsystem
3.5 - CVE-2023-4261 - Buffer overflow vulnerability in the Zephyr IPC subsystem (unreleased)
3.6 - CVE-2023-4262 - Buffer overflow vulnerabilities in the Zephyr Mgmt subsystem
3.7 - CVE-2023-4263 - Buffer overflow vulnerability in the Zephyr IEEE 802.15.4 driver
3.8 - CVE-2023-4264 - Buffer overflow vulnerabilities in the Zephyr Bluetooth subsystem
3.9 - CVE-2023-4265 - Two buffer overflow vulnerabilities in Zephyr USB code
3.10 - CVE-2023-5139 - Buffer overflow vulnerability in the Zephyr STM32 Crypto driver
3.11 - CVE-2023-5184 - Signed to unsigned conversion errors and buffer overflow vulnerabilities in the Zephyr IPM driver
3.12 - CVE-2023-5753 - Other buffer overflow vulnerabilities in the Zephyr Bluetooth subsystem
4 - Affected products
5 - Remediation
6 - Disclosure timeline
7 - Acknowledgements
8 - References
–[ 1 - Summary
“When hackers tell me it’s so hard to find bugs, I tell them to stop
looking for hard bugs.”
– Dave Aitel
The Zephyr Project [1] is an open source collaborative effort sponsored by
the Linux Foundation. It unites developers and users in building a
best-in-class, small, scalable, real-time operating system (RTOS) optimized
for resource-constrained IoT devices, across multiple microcontroller
architectures.
We reviewed Zephyr’s source code hosted on GitHub [2] and identified
multiple security vulnerabilities that may cause memory corruption. Their
impacts range from denial of service to potential arbitrary code execution.
–[ 2 - Background
While going through the awesome OpenSecurityTraining2 (OST2) Vulns1001 and
Vulns1002 training courses [3] [4], we discovered the Zephyr Project. It
immediately picked our interest and therefore we decided to review its
source code.
During the review, we made heavy use of our Semgrep C/C++ ruleset [5] to
identify hotspots in code on which to focus our attention. We also took
advantage of this opportunity to improve our ruleset.
–[ 3 - Vulnerabilities
The vulnerabilities resulting from our source code review are briefly
described in the following sections.
–[ 3.1 - CVE-2023-3725 - Buffer overflow vulnerability in the Zephyr CANbus subsystem
We spotted a buffer overflow vulnerability at the following location in the
Zephyr CANbus subsystem source code:
- /subsys/canbus/isotp/isotp.c
Ineffective size check due to assert and stack-based buffer overflow in
/subsys/canbus/isotp/isotp.c:
static inline int send_sf(struct isotp_send_ctx *ctx)
{
struct can_frame frame = {
.flags = ctx->tx_addr.ide != 0 ? CAN_FRAME_IDE : 0,
.id = ctx->tx_addr.ext_id
};
size_t len = get_ctx_data_length(ctx);
int index = 0;
int ret;
const uint8_t *data;
data = get_data_ctx(ctx);
pull_data_ctx(ctx, len);
if (ctx->tx_addr.use_ext_addr) {
frame.data[index++] = ctx->tx_addr.ext_addr;
}
frame.data[index++] = ISOTP_PCI_TYPE_SF | len;
__ASSERT_NO_MSG(len <= ISOTP_CAN_DL - index);
memcpy(&frame.data[index], data, len); /* VULN */
#ifdef CONFIG_ISOTP_ENABLE_TX_PADDING
/* AUTOSAR requirement SWS_CanTp_00348 */
memset(&frame.data[index + len], 0xCC, ISOTP_CAN_DL - len - index);
frame.dlc = ISOTP_CAN_DL;
#else
frame.dlc = len + index;
#endif
ctx->state = ISOTP_TX_SEND_SF;
ret = can_send(ctx->can_dev, &frame, K_MSEC(ISOTP_A),
send_can_tx_cb, ctx);
return ret;
}
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/61502
https://github.com/zephyrproject-rtos/zephyr/pull/61516
https://github.com/zephyrproject-rtos/zephyr/pull/61517
https://github.com/zephyrproject-rtos/zephyr/pull/61518
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-2g3m-p6c7-8rr3
–[ 3.2 - CVE-2023-4257 - Unchecked user input length in the Zephyr WiFi shell module
We spotted two instances of user input with unchecked length at the
following locations in the Zephyr WiFi shell module source code:
- /subsys/net/l2/wifi/wifi_shell.c
Unchecked user input length in /subsys/net/l2/wifi/wifi_shell.c:
static int __wifi_args_to_params(size_t argc, char *argv[],
struct wifi_connect_req_params *params)
{
char *endptr;
int idx = 1;
if (argc < 1) {
return -EINVAL;
}
/* SSID */
params->ssid = argv[0]; /* VULN: unchecked length (should be max 32) */
params->ssid_length = strlen(params->ssid);
/* Channel (optional) */
if ((idx < argc) && (strlen(argv[idx]) <= 3)) {
...
/* PSK (optional) */
if (idx < argc) {
params->psk = argv[idx]; /* VULN: unchecked length (should be min 8, max 64) */
params->psk_length = strlen(argv[idx]);
/* Defaults */
params->security = WIFI_SECURITY_TYPE_PSK;
params->mfp = WIFI_MFP_OPTIONAL;
idx++;
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/60537
https://github.com/zephyrproject-rtos/zephyr/pull/61383
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-853q-q69w-gf5j
–[ 3.3 - CVE-2023-4259 - Buffer overflow vulnerabilities in the Zephyr eS-WiFi driver
We spotted two buffer overflow vulnerabilities at the following locations
in the Zephyr eS-WiFi driver source code:
- /drivers/wifi/eswifi/eswifi_core.c
- /drivers/wifi/eswifi/eswifi_shell.c
Off-by-one buffer overflow in /drivers/wifi/eswifi/eswifi_core.c:
int eswifi_mgmt_iface_status(const struct device *dev,
struct wifi_iface_status *status)
{
struct eswifi_dev *eswifi = dev->data;
struct eswifi_sta *sta = &eswifi->sta;
/* Update status */
eswifi_status_work(&eswifi->status_work.work);
if (!sta->connected) {
status->state = WIFI_STATE_DISCONNECTED;
return 0;
}
status->state = WIFI_STATE_COMPLETED;
strcpy(status->ssid, sta->ssid); /* VULN: off-by-one (sta->ssid[33] copied over status->ssid[32]) */
status->ssid_len = strlen(sta->ssid);
status->band = WIFI_FREQ_BAND_2_4_GHZ;
status->channel = 0;
...
Static buffer overflow in /drivers/wifi/eswifi/eswifi_shell.c:
static int eswifi_shell_atcmd(const struct shell *sh, size_t argc,
char **argv)
{
int i;
if (eswifi == NULL) {
shell_print(sh, "no eswifi device registered");
return -ENOEXEC;
}
if (argc < 2) {
shell_help(sh);
return -ENOEXEC;
}
eswifi_lock(eswifi);
memset(eswifi->buf, 0, sizeof(eswifi->buf));
for (i = 1; i < argc; i++) {
strcat(eswifi->buf, argv[i]); /* VULN: static buffer overflow */
}
strcat(eswifi->buf, "\r");
shell_print(sh, "> %s", eswifi->buf);
eswifi_at_cmd(eswifi, eswifi->buf);
shell_print(sh, "< %s", eswifi->buf);
eswifi_unlock(eswifi);
return 0;
}
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/63074
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-gghm-c696-f4j4
–[ 3.4 - CVE-2023-4260 - Off-by-one buffer overflow vulnerability in the Zephyr FS subsystem
We spotted an off-by-one buffer overflow vulnerability at the following
location in the Zephyr FS subsystem source code:
- /subsys/fs/fuse_fs_access.c
If the string passed to the following function via the path
parameter is
PATH_MAX chars long (including the NUL terminator), the insecure sprintf()
function call marked below writes one NUL byte off the stack variable
mount_path
:
static int fuse_fs_access_readdir(const char *path, void *buf,
fuse_fill_dir_t filler, off_t off,
struct fuse_file_info *fi)
{
struct fs_dir_t dir;
struct fs_dirent entry;
int err;
struct stat stat;
ARG_UNUSED(off);
ARG_UNUSED(fi);
if (strcmp(path, "/") == 0) {
return fuse_fs_access_readmount(buf, filler);
}
fs_dir_t_init(&dir);
if (is_mount_point(path)) {
/* File system API expects trailing slash for a mount point
* directory but FUSE strips the trailing slashes from
* directory names so add it back.
*/
char mount_path[PATH_MAX];
sprintf(mount_path, "%s/", path); /* VULN */
err = fs_opendir(&dir, mount_path);
} else {
err = fs_opendir(&dir, path);
}
...
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/63079
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-gj27-862r-55wh
–[ 3.5 - CVE-2023-4261 - Buffer overflow vulnerability in the Zephyr IPC subsystem (unreleased)
Since this vulnerability was not fixed in Zephyr RTOS 3.5.0, we are
withholding details for the time being.
Once a fix is available, the advisory will be published on GitHub at the
following URL:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-5954-jcv4-7rvm
–[ 3.6 - CVE-2023-4262 - Buffer overflow vulnerabilities in the Zephyr Mgmt subsystem
We spotted a few buffer overflow vulnerabilities at the following locations
in the Zephyr Mgmt subsystem source code:
- /subsys/mgmt/mcumgr/transport/src/smp.c
- /subsys/mgmt/osdp/src/osdp_cp.c
Buffer overflow in /subsys/mgmt/mcumgr/transport/src/smp.c:
void *smp_alloc_rsp(const void *req, void *arg)
{
const struct net_buf *req_nb;
struct net_buf *rsp_nb;
struct smp_transport *smpt = arg;
req_nb = req;
rsp_nb = smp_packet_alloc();
if (rsp_nb == NULL) {
return NULL;
}
if (smpt->functions.ud_copy) {
smpt->functions.ud_copy(rsp_nb, req_nb);
} else {
memcpy(net_buf_user_data(rsp_nb),
net_buf_user_data((void *)req_nb),
req_nb->user_data_size); /* VULN */
}
return rsp_nb;
}
Buffer overflow due to assert in /subsys/mgmt/osdp/src/osdp_cp.c:
static int cp_build_command(struct osdp_pd *pd, uint8_t *buf, int max_len)
{
struct osdp_cmd *cmd = NULL;
int len = 0;
int data_off = osdp_phy_packet_get_data_offset(pd, buf);
#ifdef CONFIG_OSDP_SC_ENABLED
uint8_t *smb = osdp_phy_packet_get_smb(pd, buf);
#endif
buf += data_off;
max_len -= data_off;
if (max_len <= 0) {
return OSDP_CP_ERR_GENERIC;
}
switch (pd->cmd_id) {
...
case CMD_TEXT:
cmd = (struct osdp_cmd *)pd->ephemeral_data;
assert_buf_len(CMD_TEXT_LEN + cmd->text.length, max_len); /* VULN: assert */
buf[len++] = pd->cmd_id;
buf[len++] = cmd->text.reader;
buf[len++] = cmd->text.control_code;
buf[len++] = cmd->text.temp_time;
buf[len++] = cmd->text.offset_row;
buf[len++] = cmd->text.offset_col;
buf[len++] = cmd->text.length;
memcpy(buf + len, cmd->text.data, cmd->text.length); /* VULN: buffer overflow */
len += cmd->text.length;
break;
Buffer overflows due to assert in /subsys/mgmt/osdp/src/osdp_pd.c:
static int pd_build_reply(struct osdp_pd *pd, uint8_t *buf, int max_len)
{
int ret = OSDP_PD_ERR_GENERIC;
int i, len = 0;
struct osdp_cmd *cmd;
struct osdp_event *event;
int data_off = osdp_phy_packet_get_data_offset(pd, buf);
#ifdef CONFIG_OSDP_SC_ENABLED
uint8_t *smb = osdp_phy_packet_get_smb(pd, buf);
#endif
buf += data_off;
max_len -= data_off;
switch (pd->reply_id) {
...
case REPLY_KEYPPAD:
event = (struct osdp_event *)pd->ephemeral_data;
assert_buf_len(REPLY_KEYPAD_LEN + event->keypress.length, max_len); /* VULN: assert */
buf[len++] = pd->reply_id;
buf[len++] = (uint8_t)event->keypress.reader_no;
buf[len++] = (uint8_t)event->keypress.length;
memcpy(buf + len, event->keypress.data, event->keypress.length); /* VULN: buffer overflow */
len += event->keypress.length;
ret = OSDP_PD_ERR_NONE;
break;
case REPLY_RAW: {
int len_bytes;
event = (struct osdp_event *)pd->ephemeral_data;
len_bytes = (event->cardread.length + 7) / 8;
assert_buf_len(REPLY_RAW_LEN + len_bytes, max_len); /* VULN: assert */
buf[len++] = pd->reply_id;
buf[len++] = (uint8_t)event->cardread.reader_no;
buf[len++] = (uint8_t)event->cardread.format;
buf[len++] = BYTE_0(event->cardread.length);
buf[len++] = BYTE_1(event->cardread.length);
memcpy(buf + len, event->cardread.data, len_bytes); /* VULN: buffer overflow */
len += len_bytes;
ret = OSDP_PD_ERR_NONE;
break;
}
case REPLY_FMT:
event = (struct osdp_event *)pd->ephemeral_data;
assert_buf_len(REPLY_FMT_LEN + event->cardread.length, max_len); /* VULN: assert */
buf[len++] = pd->reply_id;
buf[len++] = (uint8_t)event->cardread.reader_no;
buf[len++] = (uint8_t)event->cardread.direction;
buf[len++] = (uint8_t)event->cardread.length;
memcpy(buf + len, event->cardread.data, event->cardread.length); /* VULN: buffer overflow */
len += event->cardread.length;
ret = OSDP_PD_ERR_NONE;
break;
...
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-56p9-5p3v-hhrc
–[ 3.7 - CVE-2023-4263 - Buffer overflow vulnerability in the Zephyr IEEE 802.15.4 driver
We spotted a buffer overflow vulnerability at the following location in the
Zephyr IEEE 802.15.4 driver source code:
- /drivers/ieee802154/ieee802154_nrf5.c
Buffer overflow in drivers/ieee802154/ieee802154_nrf5.c:
static int nrf5_tx(const struct device *dev,
enum ieee802154_tx_mode mode,
struct net_pkt *pkt,
struct net_buf *frag)
{
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
uint8_t payload_len = frag->len;
uint8_t *payload = frag->data;
bool ret = true;
LOG_DBG("%p (%u)", payload, payload_len);
nrf5_radio->tx_psdu[0] = payload_len + NRF5_FCS_LENGTH;
memcpy(nrf5_radio->tx_psdu + 1, payload, payload_len); /* VULN: stack-based buffer overflow due to unchecked payload_len */
/* Reset semaphore in case ACK was received after timeout */
k_sem_reset(&nrf5_radio->tx_wait);
...
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/60528
https://github.com/zephyrproject-rtos/zephyr/pull/61384
https://github.com/zephyrproject-rtos/zephyr/pull/61216
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rf6q-rhhp-pqhf
–[ 3.8 - CVE-2023-4264 - Buffer overflow vulnerabilities in the Zephyr Bluetooth subsystem
We spotted a few buffer overflow vulnerabilities at the following locations
in the Zephyr Bluetooth subsystem source code:
- /subsys/bluetooth/audio/tbs.c
- /subsys/bluetooth/audio/shell/mcc.c
- /subsys/bluetooth/audio/shell/media_controller.c
- /subsys/bluetooth/host/conn.c
- /subsys/bluetooth/mesh/beacon.c
- /subsys/bluetooth/mesh/prov_device.c
- /subsys/bluetooth/mesh/provisioner.c
- /subsys/bluetooth/mesh/shell/rpr.c
Static buffer overflows in /subsys/bluetooth/audio/tbs.c:
int bt_tbs_remote_incoming(uint8_t bearer_index, const char *to,
const char *from, const char *friendly_name)
{
struct tbs_service_inst *inst;
struct bt_tbs_call *call = NULL;
size_t local_uri_ind_len;
size_t remote_uri_ind_len;
size_t friend_name_ind_len;
...
inst = &svc_insts[bearer_index];
...
if (friendly_name) {
inst->friendly_name.call_index = call->index;
(void)strcpy(inst->friendly_name.uri, friendly_name); /* VULN */
friend_name_ind_len = strlen(from) + 1;
...
if (IS_ENABLED(CONFIG_BT_GTBS)) {
...
if (friendly_name) {
gtbs_inst.friendly_name.call_index = call->index;
(void)strcpy(gtbs_inst.friendly_name.uri, friendly_name); /* VULN */
friend_name_ind_len = strlen(from) + 1;
...
Stack-based buffer overflow in /subsys/bluetooth/audio/shell/mcc.c:
#ifdef CONFIG_BT_MCC_OTS
static int cmd_mcc_send_search_raw(const struct shell *sh, size_t argc,
char *argv[])
{
int result;
struct mpl_search search;
search.len = strlen(argv[1]);
memcpy(search.search, argv[1], search.len); /* VULN */
LOG_DBG("Search string: %s", argv[1]);
result = bt_mcc_send_search(default_conn, &search);
if (result) {
shell_print(sh, "Fail: %d", result);
}
return result;
}
Stack-based buffer overflow in
/subsys/bluetooth/audio/shell/media_controller.c:
#ifdef CONFIG_BT_OTS
static int cmd_media_set_search(const struct shell *sh, size_t argc, char *argv[])
{
/* TODO: Currently takes the raw search as input - add parameters
* and build the search item here
*/
struct mpl_search search;
int err;
search.len = strlen(argv[1]);
memcpy(search.search, argv[1], search.len); /* VULN */
LOG_DBG("Search string: %s", argv[1]);
err = media_proxy_ctrl_send_search(current_player, &search);
if (err) {
shell_error(ctx_shell, "Search send failed (%d)", err);
}
return err;
}
Heap-based buffer overflow in /subsys/bluetooth/host/conn.c:
#if defined(CONFIG_BT_SMP)
...
int bt_conn_le_start_encryption(struct bt_conn *conn, uint8_t rand[8],
uint8_t ediv[2], const uint8_t *ltk, size_t len)
{
struct bt_hci_cp_le_start_encryption *cp;
struct net_buf *buf;
buf = bt_hci_cmd_create(BT_HCI_OP_LE_START_ENCRYPTION, sizeof(*cp));
if (!buf) {
return -ENOBUFS;
}
cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
memcpy(&cp->rand, rand, sizeof(cp->rand));
memcpy(&cp->ediv, ediv, sizeof(cp->ediv));
memcpy(cp->ltk, ltk, len); /* VULN */
if (len < sizeof(cp->ltk)) {
(void)memset(cp->ltk + len, 0, sizeof(cp->ltk) - len);
}
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_START_ENCRYPTION, buf, NULL);
}
Ineffective size check due to assert and buffer overflow in
/subsys/bluetooth/mesh/beacon.c:
void bt_mesh_beacon_priv_random_get(uint8_t *random, size_t size)
{
__ASSERT(size <= sizeof(priv_random.val), "Invalid random value size %u", size);
memcpy(random, priv_random.val, size); /* VULN */
}
Static buffer overflow in /subsys/bluetooth/mesh/prov_device.c (conf_size
could be 32 and not 16):
static void prov_confirm(const uint8_t *data)
{
uint8_t conf_size = bt_mesh_prov_auth_size_get();
LOG_DBG("Remote Confirm: %s", bt_hex(data, conf_size));
memcpy(bt_mesh_prov_link.conf, data, conf_size); /* VULN */
notify_input_complete();
send_confirm();
}
Static buffer overflow in /subsys/bluetooth/mesh/provisioner.c (conf_size
could be 32 and not 16):
static void prov_confirm(const uint8_t *data)
{
uint8_t conf_size = bt_mesh_prov_auth_size_get();
LOG_DBG("Remote Confirm: %s", bt_hex(data, conf_size));
if (!memcmp(data, bt_mesh_prov_link.conf, conf_size)) {
LOG_ERR("Confirm value is identical to ours, rejecting.");
prov_fail(PROV_ERR_CFM_FAILED);
return;
}
memcpy(bt_mesh_prov_link.conf, data, conf_size); /* VULN */
send_random();
}
Stack-based buffer overflow in /subsys/bluetooth/mesh/shell/rpr.c:
static void rpr_scan_report(struct bt_mesh_rpr_cli *cli,
const struct bt_mesh_rpr_node *srv,
struct bt_mesh_rpr_unprov *unprov,
struct net_buf_simple *adv_data)
{
char uuid_hex_str[32 + 1];
bin2hex(unprov->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
shell_print(bt_mesh_shell_ctx_shell,
"Server 0x%04x:\n"
"\tuuid: %s\n"
"\tOOB: 0x%04x",
srv->addr, uuid_hex_str, unprov->oob);
while (adv_data && adv_data->len > 2) {
uint8_t len, type;
uint8_t data[31];
len = net_buf_simple_pull_u8(adv_data) - 1;
type = net_buf_simple_pull_u8(adv_data);
memcpy(data, net_buf_simple_pull_mem(adv_data, len), len); /* VULN */
data[len] = '\0';
if (type == BT_DATA_URI) {
shell_print(bt_mesh_shell_ctx_shell, "\tURI: \"\\x%02x%s\"",
data[0], &data[1]);
} else if (type == BT_DATA_NAME_COMPLETE) {
shell_print(bt_mesh_shell_ctx_shell, "\tName: \"%s\"", data);
} else {
char string[64 + 1];
bin2hex(data, len, string, sizeof(string));
shell_print(bt_mesh_shell_ctx_shell, "\t0x%02x: %s", type, string);
}
}
}
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/58834
https://github.com/zephyrproject-rtos/zephyr/pull/60465
https://github.com/zephyrproject-rtos/zephyr/pull/61845
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rgx6-3w4j-gf5j
–[ 3.9 - CVE-2023-4265 - Two buffer overflow vulnerabilities in Zephyr USB code
We found two buffer overflow vulnerabilities at the following locations:
- /drivers/usb/device/usb_dc_native_posix.c#L359
- /subsys/usb/device/class/netusb/function_rndis.c#L841
The first vulnerability is located in the usb_dc_ep_write() function:
int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data,
const uint32_t data_len, uint32_t * const ret_bytes)
{
LOG_DBG("ep %x len %u", ep, data_len);
if (!usbip_ctrl.attached || !usbip_ep_is_valid(ep)) {
LOG_ERR("Not attached / Invalid endpoint: EP 0x%x", ep);
return -EINVAL;
}
/* Check if IN ep */
if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) {
return -EINVAL;
}
/* Check if ep enabled */
if (!usbip_ep_is_enabled(ep)) {
LOG_WRN("ep %x disabled", ep);
return -EINVAL;
}
if (USB_EP_GET_IDX(ep) == 0) {
if (!usbip_send_common(ep, data_len)) {
return -EIO;
}
if (usbip_send(ep, data, data_len) != data_len) {
return -EIO;
}
} else {
uint8_t ep_idx = USB_EP_GET_IDX(ep);
struct usb_ep_ctrl_prv *ctrl = &usbip_ctrl.in_ep_ctrl[ep_idx];
memcpy(ctrl->buf, data, data_len); /* VULN */
ctrl->buf_len = data_len;
}
if (ret_bytes) {
*ret_bytes = data_len;
}
return 0;
}
A check on data_len
is missing. Because data
and data_len
are
potentially attacker-controlled, the fixed-size buffer buf
in the
following structure could overflow during memcpy(), thus leading to denial
of service or arbitrary code execution:
struct usb_ep_ctrl_prv {
u8_t ep_ena;
u16_t mps;
usb_dc_ep_callback cb;
u32_t data_len;
u8_t buf[64];
u8_t buf_len;
};
The second vulnerability is located in the handle_encapsulated_rsp()
function:
static int handle_encapsulated_rsp(uint8_t **data, uint32_t *len)
{
struct net_buf *buf;
LOG_DBG("");
buf = net_buf_get(&rndis_tx_queue, K_NO_WAIT);
if (!buf) {
LOG_ERR("Error getting response buffer");
*len = 0U;
return -ENODATA;
}
if (VERBOSE_DEBUG) {
net_hexdump("RSP <", buf->data, buf->len);
}
memcpy(*data, buf->data, buf->len); /* VULN */
*len = buf->len;
net_buf_unref(buf);
return 0;
}
A check on buf->len
is missing. Because buf->data
and buf->len
are
potentially attacker-controlled, the data
buffer could overflow due to
memcpy(), thus leading to denial of service or arbitrary code execution.
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/59018
https://github.com/zephyrproject-rtos/zephyr/pull/59157
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-4vgv-5r6q-r6xh
–[ 3.10 - CVE-2023-5139 - Buffer overflow vulnerability in the Zephyr STM32 Crypto driver
We spotted a buffer overflow vulnerability at the following location in the
Zephyr STM32 Crypto driver source code:
- /drivers/crypto/crypto_stm32.c
Buffer overflow due to ineffective assert check in
/drivers/crypto/crypto_stm32.c:
static void copy_reverse_words(uint8_t *dst_buf, int dst_len,
uint8_t *src_buf, int src_len)
{
int i;
__ASSERT_NO_MSG(dst_len >= src_len); /* VULN: assert */
__ASSERT_NO_MSG((dst_len % 4) == 0);
memcpy(dst_buf, src_buf, src_len); /* VULN: buffer overflow */
for (i = 0; i < dst_len; i += sizeof(uint32_t)) {
sys_mem_swap(&dst_buf[i], sizeof(uint32_t));
}
}
The function copy_reverse_words() is called in a few locations that might
be problematic, because src_len
might be attacker-controlled:
- crypto_stm32_ctr_encrypt()
- crypto_stm32_ctr_decrypt()
- crypto_stm32_session_setup()
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/61839
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rhrc-pcxp-4453
–[3.11 - CVE-2023-5184 - Signed to unsigned conversion errors and buffer overflow vulnerabilities in the Zephyr IPM driver
We spotted two signed to unsigned conversion errors and buffer overflow
vulnerabilities at the following locations in the Zephyr IPM driver source
code:
- /drivers/ipm/ipm_imx.c
- /drivers/ipm/ipm_mcux.c
Buffer overflow if size
is negative, due to signed/unsigned conversion in
/drivers/ipm/ipm_imx.c:
static int imx_mu_ipm_send(const struct device *dev, int wait, uint32_t id,
const void *data, int size)
{
const struct imx_mu_config *config = dev->config;
MU_Type *base = MU(config);
uint32_t data32[IMX_IPM_DATA_REGS];
#if !IS_ENABLED(CONFIG_IPM_IMX_REV2)
mu_status_t status;
#endif
int i;
if (id > CONFIG_IPM_IMX_MAX_ID_VAL) {
return -EINVAL;
}
if (size > CONFIG_IPM_IMX_MAX_DATA_SIZE) { /* VULN: ineffective check if size is negative */
return -EMSGSIZE;
}
/* Actual message is passing using 32 bits registers */
memcpy(data32, data, size); /* VULN: buffer overflow if size is negative */
...
Buffer overflow if size
is negative, due to signed/unsigned conversion in
/drivers/ipm/ipm_mcux.c:
static int mcux_mailbox_ipm_send(const struct device *d, int wait,
uint32_t id,
const void *data, int size)
{
const struct mcux_mailbox_config *config = d->config;
MAILBOX_Type *base = config->base;
uint32_t data32[MCUX_IPM_DATA_REGS]; /* Until we change API
* to uint32_t array
*/
unsigned int flags;
int i;
ARG_UNUSED(wait);
if (id > MCUX_IPM_MAX_ID_VAL) {
return -EINVAL;
}
if (size > MCUX_IPM_DATA_REGS * sizeof(uint32_t)) { /* VULN: ineffective check if size is negative */
return -EMSGSIZE;
}
flags = irq_lock();
/* Actual message is passing using 32 bits registers */
memcpy(data32, data, size); /* VULN: buffer overflow if size is negative */
...
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/63069
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-8x3p-q3r5-xh9g
–[3.12 - CVE-2023-5753 - Other buffer overflow vulnerabilities in the Zephyr Bluetooth subsystem
We spotted some additional buffer overflow vulnerabilities at the following
locations in the Zephyr Bluetooth subsystem source code:
- /subsys/bluetooth/controller/ll_sw/ull_adv.c
- /subsys/bluetooth/host/hci_core.c
- /subsys/bluetooth/host/iso.c
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()
Fixes:
https://github.com/zephyrproject-rtos/zephyr/pull/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.
See also:
https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-hmpr-px56-rvww
–[ 4 - Affected products
Zephyr 3.4.0 and earlier versions are affected by the vulnerabilities
discussed in this advisory, except for CVE-2023-4265 (Two buffer overflow
vulnerabilities in Zephyr USB code) that affects Zephyr 3.3.0 and earlier,
and CVE-2023-4261 that affects Zephyr 3.5.0 and earlier.
–[ 5 - Remediation
On 2023-10-20 the Zephyr Project has released version 3.5.0 of their RTOS
[6] that contains fixes for all vulnerabilities discussed in this advisory,
except for CVE-2023-4265 that was already fixed in Zephyr 3.4.0, and
CVE-2023-4261 that will be fixed in a future update.
Please check the official Zephyr Project channels for further information
about fixes and backported patches for older but still maintained releases
of the Zephyr RTOS [7].
–[ 6 - Disclosure timeline
We reported the vulnerabilities discussed in this advisory to the Zephyr
Project between May and July 2023, using GitHub’s security advisories
feature [8].
Private vulnerability reporting allows security researchers to report
vulnerabilities securely in a repository. It’s an excellent way to
streamline coordinated disclosure and we wish more maintainers enabled it.
–[ 7 - Acknowledgements
We would like to thank the Zephyr Project’s development team and Flavio
Ceolin in particular for triaging and fixing the reported vulnerabilities.
–[ 8 - References
[1] https://www.zephyrproject.org/
[2] https://github.com/zephyrproject-rtos/zephyr
[3] https://ost2.fyi/Vulns1001
[4] https://ost2.fyi/Vulns1002
[5] https://github.com/0xdea/semgrep-rules
[6] https://github.com/zephyrproject-rtos/zephyr/releases/tag/v3.5.0
[7] https://github.com/zephyrproject-rtos/zephyr/security
[8] https://docs.github.com/en/code-security/security-advisories
Copyright © 2023 Marco Ivaldi and Humanativa Group. All rights reserved.
Related news
Potential buffer overflow vulnerability at the following location in the Zephyr STM32 Crypto driver
Potential buffer overflows in the Bluetooth subsystem due to asserts being disabled in /subsys/bluetooth/host/hci_core.c
Unchecked user input length in /subsys/net/l2/wifi/wifi_shell.c can cause buffer overflows.
Potential buffer overflow vulnerability in the Zephyr IEEE 802.15.4 nRF 15.4 driver
Potential buffer overflow vulnerability in the Zephyr CAN bus subsystem
Two potential signed to unsigned conversion errors and buffer overflow vulnerabilities at the following locations in the Zephyr IPM drivers.
Possible buffer overflow in Zephyr mgmt subsystem when asserts are disabled
Potential buffer overflow vulnerabilities n the Zephyr Bluetooth subsystem.
Potential off-by-one buffer overflow vulnerability in the Zephyr fuse file system.
Two potential buffer overflow vulnerabilities at the following locations in the Zephyr eS-WiFi driver source code.
Potential buffer overflow vulnerabilities in the following locations: https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/usb/device/usb_dc_native_posix.c#L359 https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/usb/device/usb_dc_native_posix.c#L359 https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/usb/device/class/netusb/function_rndis... https://github.com/zephyrproject-rtos/zephyr/blob/main/subsys/usb/device/class/netusb/function_rndis.c#L841