Vulnerabilities
Vulnerable Software
Zephyrproject:  >> Zephyr  >> 3.6.0  Security Vulnerabilities
The DesignWare SPI driver (drivers/spi/spi_dw.c) computed the SPI BAUDR clock divider as info->clock_frequency / config->frequency without validating config->frequency. spi_transceive is a Zephyr __syscall and its verify handler (drivers/spi/spi_handlers.c) copies the caller-supplied spi_config from userspace without checking the frequency field, so a userspace thread that has been granted access to a DesignWare SPI device kernel object can pass frequency = 0 and trigger an unsigned integer divide-by-zero in spi_dw_configure(). On Cortex-M Mainline (SCB->CCR.DIV_0_TRP is set in z_arm_fault_init()) and on ARC (a dedicated __ev_div_zero vector) this raises a CPU exception, resulting in a kernel fault and local denial of service. The fix rejects zero frequency and frequencies above clock_frequency / 2 (the DesignWare SSI databook minimum SCKDIV of 2) with -EINVAL. The defect affects all Zephyr releases up to and including v4.4.0; exploitation requires CONFIG_USERSPACE=y and an unprivileged thread already granted SPI driver permission. There is no memory-corruption or information-disclosure impact.
CVSS Score
3.3
EPSS Score
0.001
Published
2026-07-21
In Zephyr's Bluetooth Mesh PB-ADV provisioning bearer (subsys/bluetooth/mesh/pb_adv.c), prov_msg_recv() rescheduled the provisioning protocol watchdog timer unconditionally at the top of the function, before the FCS check and before the ADV_LINK_INVALID check. Once a provisioning attempt fails, prov_failed() sets ADV_LINK_INVALID and the only recovery path is the protocol timer firing (protocol_timeout -> prov_link_close -> close_link -> reset_adv_link and re-enabling of scanning and the unprovisioned device beacon). A remote, unauthenticated attacker on the BLE advertising channel can first induce a provisioning failure (e.g. with a malformed generic-provisioning PDU) and then transmit any FCS-valid PB-ADV transaction PDU on the same link ID more often than once per protocol timeout (60 s, or 120 s for OOB input/output). Because each such packet reset the timer even on an invalidated link, protocol_timeout never fired, the dead link was never torn down, and the device remained pinned in an un-provisionable state with its unprovisioned beacon disabled and new Link Open requests rejected. PB-ADV PDUs are processed without authentication and the FCS is a keyless CRC, so no pairing or prior trust is required and the attacker chooses the link ID itself. The impact is a persistent denial of provisioning/re-provisioning service; there is no memory-safety, confidentiality, or integrity impact. The vulnerable code shipped in releases through v4.4.1. The fix moves the timer reschedule to after the ADV_LINK_INVALID check (and the FCS check before the reset) so an invalidated link can no longer be kept alive by incoming packets.
CVSS Score
4.3
EPSS Score
0.002
Published
2026-07-21
The CONFIG_USERSPACE syscall verifier z_vrfy_k_poll() in kernel/poll.c allocates a kernel-side copy of the user-supplied k_poll_event[] via z_thread_malloc() and then validates each event's object handle. Before this fix, validation used K_OOPS(K_SYSCALL_OBJ(...)) inline inside the loop, which kills the calling thread without freeing events_copy. A user thread can pass num_events >= 1 with a forged object handle to leak the allocation; because newly spawned user threads inherit the parent's resource_pool (kernel/thread.c), an attacker spawns sacrificial threads to repeat the leak until the shared kernel heap is exhausted. Once depleted, legitimate kernel allocations from that pool (k_queue alloc nodes, k_msgq buffers, future k_poll calls, etc.) fail, causing a system-level denial of service. The fix replaces each inline K_OOPS with a conditional goto oops_free so the buffer is freed before the thread is killed. Affects Zephyr releases from v1.12.0 (when k_poll was first exposed to user mode) through v4.4.1.
CVSS Score
6.5
EPSS Score
0.001
Published
2026-07-21
The NXP LPUART serial driver (drivers/serial/uart_mcux_lpuart.c), when CONFIG_UART_USE_RUNTIME_CONFIGURE is enabled, called LPUART_Deinit() at the start of mcux_lpuart_configure(), which disables the LPUART peripheral clocks. The requested configuration is validated only afterwards (in mcux_lpuart_configure_basic), and unsupported parity/data-bit/stop-bit/flow-control values return -ENOTSUP before the clock is re-enabled. As a result, a uart_configure() request with an unsupported configuration left the LPUART in a clock-disabled state; any subsequent access to LPUART registers (poll_out/poll_in, interrupt handling, or a later reconfigure) faults on the gated peripheral and escalates to a hard fault, crashing the system. uart_configure() is a Zephyr syscall whose verifier (z_vrfy_uart_configure) only checks that cfg is readable user memory and forwards the caller-supplied configuration unchanged, so an unprivileged userspace thread with access to an LPUART device can deterministically trigger the fault, a persistent system-wide denial of service. Introduced in v2.5.0 and present in all subsequent releases until this fix, which removes the LPUART_Deinit() call and instead only disables the transmitter/receiver, leaving the clock running.
CVSS Score
5.5
EPSS Score
0.001
Published
2026-07-21
The CONFIG_USERSPACE verification handler for the k_thread_name_copy() system call (z_vrfy_k_thread_name_copy() in kernel/thread.c) calls k_object_find() on the caller-supplied thread pointer and then dereferences the returned struct k_object without checking it for NULL. k_object_find() returns NULL whenever the supplied pointer is not a registered (static or dynamic) kernel object. The pre-fix guard tested thread == NULL instead of ko == NULL, so an unprivileged user-mode thread that invokes k_thread_name_copy() with any non-NULL but unregistered pointer (e.g. an arbitrary address) passes the NULL test, after which the verifier reads ko->type through a NULL pointer. Because the syscall verifier runs in supervisor mode, this NULL dereference is a kernel-mode fault that halts or reboots the system, allowing untrusted user code to crash the kernel across the userspace security boundary (denial of service). The marshaller passes the thread argument to the verifier without any prior K_SYSCALL_OBJ validation, so the bad pointer reaches the defect directly. The flaw affects builds with CONFIG_USERSPACE and CONFIG_THREAD_NAME enabled and has been present since the special-case lookup was introduced around v2.0.0; it is present in v4.4.0 and earlier. The fix changes the guard to check the k_object_find() return value (ko == NULL) before dereferencing it.
CVSS Score
5.5
EPSS Score
0.002
Published
2026-07-14
parse_ipv4() in subsys/net/ip/utils.c (reached via net_ipaddr_parse() for strings of the form "a.b.c.d:port") copies the port substring into a fixed 17-byte stack buffer (char ipaddr[NET_IPV4_ADDR_LEN + 1]) using a length of str_len - end - 1, where str_len is the full, unbounded input length and end is only the (<=15-byte) offset of the ':' delimiter. Because the destination size is never consulted, a crafted address string with a long suffix after the colon (e.g. "1.2.3.4:" followed by hundreds of bytes) causes an out-of-bounds stack write whose length and contents are fully attacker-controlled (memcpy of the suffix plus a trailing NUL), enabling memory corruption and at minimum a denial of service, and potentially control-flow hijack. The parser is reached from the standard socket API (zsock_getaddrinfo / literal-address resolution), DNS server-string configuration, and the eswifi Wi-Fi co-processor DNS-response path, so an application that resolves a network-influenced address string is exposed. The bug was introduced when the parser was added (Zephyr v1.9.0) and shipped in all releases through v4.4.0. The fix removes the unbounded copy and validates the port length before copying into a small dedicated buffer. Note: the equivalent IPv6 "[addr]:port" path in parse_ipv6() retains the same unbounded copy at this commit and remains a separate, still-reachable instance of the defect.
CVSS Score
8.1
EPSS Score
0.007
Published
2026-07-12
Zephyr's dynamic kernel-object tracking (kernel/userspace/userspace.c, formerly kernel/userspace.c) maintains a doubly-linked list (obj_list) of dynamically allocated kernel objects. Iteration over this list in k_object_wordlist_foreach() was performed under lists_lock using the SAFE iterator (which caches the next node), but list removal and freeing of nodes was performed under different, disjoint spinlocks: objfree_lock in k_object_free() and obj_lock in unref_check(). On an SMP system, while one CPU iterated obj_list under lists_lock, another CPU could unlink and k_free() the dyn_obj node that the iterator had cached as its next pointer, causing the iterator to dereference freed kernel memory (use-after-free / dangling list traversal). All of the racing operations are reachable from unprivileged user-mode threads via system calls: k_object_alloc/k_object_alloc_size and k_object_release drive removals through unref_check() (under obj_lock), while k_thread_abort and thread creation drive the iteration through k_thread_perms_all_clear()/k_thread_perms_inherit() (under lists_lock). A deprivileged user thread on a CONFIG_SMP + CONFIG_USERSPACE build can therefore corrupt the kernel's object-tracking structures across the userspace security boundary, yielding kernel memory corruption (potential privilege escalation) or a kernel crash (denial of service). The fix removes objfree_lock and serializes every obj_list modification under lists_lock, including holding it across find+remove in k_object_free() and around unref_check() in k_thread_perms_clear(). Affects CONFIG_SMP+CONFIG_USERSPACE+CONFIG_DYNAMIC_OBJECTS configurations; the defect dates to the 2019 spinlockification (commit 8a3d57b6cc6, first released in v1.14.0) and shipped through v4.4.0.
CVSS Score
7.8
EPSS Score
0.001
Published
2026-07-12
Zephyr's DNS resolver detects mDNS (.local) queries in dns_resolve_name_internal() (subsys/net/lib/dns/resolve.c) with memcmp(strrchr(query, '.'), ".local", 7), which always reads a fixed 7 bytes from the suffix pointer. When the resolved hostname's final label is shorter than 7 bytes (e.g. names ending in .org, .com, .net, .io, or a trailing dot), the comparison reads 1-2 bytes past the string's NUL terminator. The hostname (query) is the caller-supplied name passed through the standard getaddrinfo()/dns_get_addr_info()/dns_resolve_name() path and is influenceable by operators or remote inputs (server names from configuration, parsed URLs, or app-facing interfaces). On a tightly-sized buffer with no slack (for example a userspace getaddrinfo call where the hostname is copied with k_usermode_string_alloc_copy to exactly strlen+1 bytes), the over-read crosses the allocation boundary; if that boundary is unmapped (guard page, memory-domain boundary under MPU, or an address sanitizer) the over-read faults, causing a denial of service. The over-read bytes are never returned, so there is no information disclosure. The flaw is compiled only when CONFIG_MDNS_RESOLVER is enabled, exists since v1.10.0, and is fixed by replacing the fixed-length memcmp with a NUL-safe strcmp(ptr, ".local").
CVSS Score
3.7
EPSS Score
0.004
Published
2026-07-05
The Zephyr Bluetooth controller ISO Adaptation Layer (subsys/bluetooth/controller/ll_sw/isoal.c) fails to validate the length field of a framed ISO PDU start segment. Per the Bluetooth specification a start segment (sc=0) always carries a 3-byte time_offset, so its segment-header len must be at least PDU_ISO_SEG_TIMEOFFSET_SIZE (3). isoal_check_seg_header() accepted start segments with len < 3 as valid, and isoal_rx_framed_consume() then computed length = seg_hdr->len - 3 in a uint8_t, underflowing to 253-255 when len is 0-2. That oversized length is passed to isoal_rx_append_to_sdu(), whose copy is clamped only against the destination SDU buffer size, not the source PDU length, so up to ~255 bytes of controller memory beyond the received PDU are copied (via sink_sdu_write_hci()/net_buf_add_mem) into an HCI ISO data packet and delivered to the host. The PDU and its segment headers are entirely attacker-controlled and arrive over the air, reachable through both the CIS and BIS-sync HCI data paths (hci_driver.c) and the vendor data path (ull_iso.c), so a remote CIS peer or a broadcaster the device is synced to can trigger an out-of-bounds read causing information disclosure to the host and potential denial of service (faults or malformed oversized HCI ISO packets). The flaw affects all Zephyr releases since framed ISO reception was introduced in v3.0.0. The fix rejects sc=0 segments with len < 3 in isoal_check_seg_header() and adds a guard before the subtraction in isoal_rx_framed_consume().
CVSS Score
6.5
EPSS Score
0.003
Published
2026-06-30
The Zephyr net_buf library (lib/net_buf/buf.c) manipulated both of its reference counts -- the per-header buf->ref and the per-data-block ref_count at the start of each variable/heap data allocation -- with plain non-atomic C operators (buf->ref++, if (--buf->ref > 0), if (--(*ref_count))). The API is documented as self-synchronizing: callers may share one buffer across threads (e.g. via k_fifo) and each holder independently calls net_buf_unref() with no surrounding lock. Under true concurrency (SMP, or single-core preemption between the non-atomic load and store while another context unrefs the same buffer), two holders can both observe the same prior reference value and both conclude they are the last reference. For heap/variable-data pools (mem_pool_data_unref/heap_data_unref, used by zbus message subscribers, the IP stack RX/TX buffers when CONFIG_NET_BUF_FIXED_DATA_SIZE=n, capture, wireguard, ISO-TP and usbip) this produces a double k_heap_free()/k_free() of the same block -- heap-metadata corruption and a use-after-free on the heap-hardening poison pattern. For the per-header refcount the buffer is returned to the pool free LIFO twice for any pool type (including fixed-data pools used by Bluetooth and networking), corrupting the free list so a later allocation hands the same buffer to two owners. The fix converts both refcounts to atomic_inc/atomic_dec (overlaying buf->ref in an atomic_t-sized union and changing the data-block refcount from uint8_t to atomic_t). Impact is gated on genuine concurrency and on an application architecture that shares one buffer among multiple independent unref'ers; the trigger is a refcount/timing race rather than packet content, so an external attacker has at most weak indirect influence over the race window. Affects all Zephyr releases through v4.4.0. This fix is not being backported to v3.7-branch (LTS). The backport was attempted and closed unmerged (#111181): the v3.7 networking tree has diverged from main, and the new atomic word-packing -- together with the assertions it adds -- turns pre-existing v3.7-only reference-counting defects elsewhere in the stack into hard faults, so landing the change faithfully would mean pulling an open-ended set of additional v3.7-only fixes into an LTS branch. v3.7 remains affected. Applications on v3.7 that share one net_buf across threads should serialize their own net_buf_unref() calls rather than rely on the documented self-synchronizing behaviour. The fix is on main and has been backported to v4.3-branch (#110852) and v4.4-branch (#110853).
CVSS Score
6.4
EPSS Score
0.004
Published
2026-06-30


Contact Us

Shodan ® - All rights reserved