Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessGain unprivileged user-mode thread on SMP build
-
DeliveryIssue k_timer_start and k_thread_create/abort syscalls
-
ExploitRace timer handler against wait-queue removal
-
ExecutionHandler dereferences stale/sentinel thread pointer
-
PersistOOB/use-after-free write in supervisor context
-
ImpactScheduler corruption or kernel crash
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A06:2025 - Insecure Design
ASVS 5.0
V15 - Secure Coding and Architecture Concurrency control, locking
MITRE ATT&CK
1 technique across 1 tactic: Privilege Escalation The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires all of: (1) a Zephyr build with CONFIG_MP_MAX_NUM_CPUS greater than one - the affected region is an explicit no-op on uniprocessor targets, so single-core devices are not vulnerable; (2) CONFIG_USERSPACE enabled, which exposes k_timer_start(), k_timer_status_sync(), k_thread_create(), and k_thread_abort() as system calls that an unprivileged user-mode thread can invoke; (3) local code execution on the device (per CVSS AV:L); and (4) winning a narrow timing window in which the last waiter is removed on another CPU between z_timer_expiration_handler() reading timer->wait_q and acting on it. CONFIG_WAITQ_SCALABLE widens the corruption primitive (rb_get_min() can return an arbitrary tree node). The primary limiting factors - multi-core-only, userspace-only, and an inherently non-deterministic race - mean failed attempts typically crash the kernel rather than yield controlled corruption, reducing practical weaponization. |
| Impact | This is a genuine but conditional kernel vulnerability, not a drive-by threat. The CVSS 3.1 vector (AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H = 7.0 High) is internally consistent with the description: local access (an on-device user-mode thread), high complexity (winning a narrow timing window against another CPU), and low privileges (an unprivileged thread under CONFIG_USERSPACE). The CWE-362 race condition and the three-layer precondition - CONFIG_MP_MAX_NUM_CPUS>1 AND CONFIG_USERSPACE enabled AND a successfully won interleave - sharply limit real-world exploitability; the vendor itself states the most likely outcome is a kernel crash (DoS) rather than controlled corruption. No EPSS score, KEV listing, or public exploit was provided, so there is no evidence of in-the-wild use; exploitation status is best characterized as no public exploit identified at time of analysis. Conflicting-signal note: the input Tags assert 'RCE', but the CVSS vector is AV:L (local), so this is a local kernel memory-corruption / potential local privilege escalation primitive, not remote code execution - treat the 'RCE' label with caution. Bottom line: moderate priority, driven by patch-management hygiene for SMP+userspace Zephyr builds rather than active-exploitation urgency. |
| Exploit ScenarioDerived | On a multi-core Zephyr device with CONFIG_USERSPACE enabled, an unprivileged user-mode thread repeatedly orchestrates k_timer_start()/k_timer_status_sync() against k_thread_create()/k_thread_abort() on another CPU to hit the window where z_timer_expiration_handler() reads a wait-queue head that is simultaneously being emptied. Winning the race makes the handler dereference a stale/sentinel pointer and perform out-of-bounds or use-after-free writes in supervisor context, corrupting scheduler state. No public proof-of-concept is available, and the high timing sensitivity means the realistic result is usually a kernel crash rather than reliable control. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 21, 2026
Missing scheduler-lock protection in Zephyr RTOS's z_waitq_head() helper lets a local unprivileged user-mode thread race the kernel timer expiration handler against thread abort on multi-core builds, yielding use-after-free and out-of-bounds writes performed in supervisor context along with scheduler state corruption; the more common outcome of a lost race is a kernel crash rather than controlled corruption. Only builds with CONFIG_MP_MAX_NUM_CPUS greater than one and CONFIG_USERSPACE enabled are exposed, since the affected code path is a no-op on uniprocessor targets and the required k_timer_start(), k_timer_status_sync(), k_thread_create() and k_thread_abort() primitives are syscalls. Rated CVSS 7.0 (AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H); no public exploit code or confirmed active exploitation was identified at time of analysis, and the narrow timing window keeps practical risk conditional rather than drive-by.
RemediationAI
Apply the upstream vendor fix, commit a9b21fb354e8468dd15db307c3e599dc68b7ef33, which introduces z_waitq_head_locked() for lock-holding callers, a lock-acquiring z_waitq_head() for the rest, and moves the timer expiration handler's head read, unpend and ready into one LOCK_SCHED_SPINLOCK region; verify with the vendor advisory at https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-gm6w-pv43-m3vf which release lines carry the backport. Upstream fix available (PR/commit); released patched version not independently confirmed, so re-validate the fix is present in the specific Zephyr release or vendor SDK you ship rather than assuming. Where patching is delayed, the highest-value compensating control is to build with CONFIG_USERSPACE disabled, which removes the syscall surface (k_timer_start(), k_timer_status_sync(), k_thread_create(), k_thread_abort()) an unprivileged thread needs - at the cost of losing memory-domain isolation for all application threads. Setting CONFIG_MP_MAX_NUM_CPUS to 1 makes the affected region a no-op and eliminates the race entirely, but forfeits SMP scaling and may be unacceptable on multi-core SoCs. Disabling CONFIG_WAITQ_SCALABLE narrows the corruption primitive from an arbitrary tree node to a list sentinel, reducing (not removing) the impact. Restricting local code execution and avoiding dynamic thread creation paired with k_thread_abort() on timers reduces the attack surface as a defense-in-depth measure, but none of these workarounds replaces the upstream patch.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
Zephyr's kernel wait queues (_wait_q_t) are intrusive doubly linked lists of struct k_thread nodes, mutated under the scheduler spinlock _sched_spinlock; on SMP systems with CONFIG_WAITQ_SCALABLE the queue is instead an red-black tree and the head is obtained with rb_get_min(). The helper z_waitq_head() in kernel/include/wait_q.h read the head without acquiring _sched_spinlock, relying incorrectly on caller-held subsystem locks. The dangerous caller was z_timer_expiration_handler() in kernel/timer.c, which held only timer_lock while reading timer->wait_q and then unpending, setting the return value of, and readying the retrieved thread, while halt_thread() in kernel/sched.c removes an aborted thread from the same wait queue holding only _sched_spinlock - so the two paths were never mutually exclusive. If the last waiter is removed on another CPU inside that window, sys_dlist_peek_head() can return the list sentinel (a pointer into the k_timer object itself) reinterpreted as struct k_thread *, or an arbitrary tree node under CONFIG_WAITQ_SCALABLE, or a thread that has already been unpended and, for dynamically allocated threads, freed. unpend_thread_no_timeout() then performs sys_dlist_remove() through pointers read from that bogus object and arch_thread_return_value_set() writes unconditionally through it. The root cause class is CWE-362 (concurrent execution using shared resource with improper synchronization); the fix splits the helper into z_waitq_head_locked() for callers already holding the scheduler lock and a locking z_waitq_head(), and folds the timer handler's head read, unpend and ready into a single LOCK_SCHED_SPINLOCK region.
Know when Zephyr gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
Local user-mode thread (AV:L), unprivileged syscall access (PR:L), and a narrow multi-CPU race window (AC:H) yielding supervisor OOB/UAF writes (C/I/A:H).
Primary rating from Vendor (zephyr).
CVSS VectorVendor: zephyr
DescriptionCVE.org
The kernel helper z_waitq_head() (kernel/include/wait_q.h) reads the head of a thread wait queue, but on SMP systems it was called from several places without holding the scheduler spinlock _sched_spinlock that serializes wait-queue mutation. The consequential call site is z_timer_expiration_handler() in kernel/timer.c, which held only the timer subsystem lock timer_lock while reading timer->wait_q and then unpending, setting the return value of, and readying the thread it obtained. halt_thread() in kernel/sched.c removes an aborted thread from its wait queue while holding only _sched_spinlock, so the two paths are not mutually exclusive.
When the last waiter is removed on another CPU inside that window, sys_dlist_peek_head() can return the list sentinel - a pointer into the k_timer object itself - typed as a struct k_thread * (with CONFIG_WAITQ_SCALABLE, rb_get_min() can return an arbitrary node of a tree being restructured), or it can return a pointer to a thread that has already been unpended and, for dynamically allocated threads, freed. The handler then calls unpend_thread_no_timeout(), which performs a sys_dlist_remove() through pointers read from that object, and arch_thread_return_value_set(), which writes unconditionally through the pointer.
The result is out-of-bounds and use-after-free writes in supervisor context, plus scheduler state corruption; a milder outcome is a thread that has re-pended elsewhere being woken with a success return value from an unrelated blocking call. All of the primitives needed to drive the interleaving - k_timer_start(), k_timer_status_sync(), k_thread_create() and k_thread_abort() - are system calls, so with CONFIG_USERSPACE enabled an unprivileged user-mode thread can attempt the race against kernel-owned data.
Exploitation requires a multi-CPU build (CONFIG_MP_MAX_NUM_CPUS greater than one; the affected region is a no-op on uniprocessor targets), local code execution, and winning a narrow timing window, so the practical outcome is most often a kernel crash rather than controlled corruption. The fix splits the helper into z_waitq_head_locked() for callers that already hold the scheduler spinlock and a z_waitq_head() that acquires it, and brings the timer expiration handler's head read, unpend and ready under a single LOCK_SCHED_SPINLOCK region.
Technical POC Analysis
CWE-362 (race condition / improper synchronization).
Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.
Executive ViewAI
Multi-core Zephyr RTOS builds with userspace enabled carry a race condition in the kernel wait-queue helper that can corrupt scheduler state and, in the worst case, write to memory from supervisor context on behalf of a local unprivileged thread. Product teams shipping connected embedded devices on affected configurations should care because a successful trigger is a full device compromise at the highest privilege level, though the narrow timing window and local-only access requirement make this a conditional risk rather than an internet-facing exposure. Impact concentrates on engineering and product security organizations maintaining Zephyr-based firmware rather than on corporate IT systems.
Apply vendor patch.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Race conditions occur when multiple concurrent requests exploit the brief time gap between checking a condition and acting upon it (TOCTOU - Time of Check, Time of Use).
Remote Code Execution represents the critical moment when an attacker successfully runs arbitrary code on a target system without physical access.
Potential off-by-one buffer overflow vulnerability in the Zephyr fuse file system. Rated critical severity (CVSS 10.0),
An out-of-bounds write in the Zephyr RTOS DNS resolver (dns_unpack_name()) lets a crafted DNS response corrupt memory on
Possible variant of CVE-2021-3434 in function le_ecred_reconf_req. Rated critical severity (CVSS 9.8), this vulnerabilit
Unchecked user input length in /subsys/net/l2/wifi/wifi_shell.c can cause buffer overflows. Rated critical severity (CVS
Potential buffer overflow vulnerability in the Zephyr CAN bus subsystem. Rated critical severity (CVSS 9.8), this vulner
Integer Underflow in 6LoWPAN IPHC Header Uncompression in Zephyr. Rated critical severity (CVSS 9.8), this vulnerability
Buffer overflow in Zephyr USB DFU DNLOAD. Rated critical severity (CVSS 9.8), this vulnerability is remotely exploitable
DOS: Incorrect 802154 Frame Validation for Omitted Source / Dest Addresses. Rated critical severity (CVSS 9.8), this vul
zephyr-rtos version 1.12.0 contains a NULL base pointer reference vulnerability in sys_ring_buf_put(), sys_ring_buf_get(
Potential buffer overflow vulnerabilities n the Zephyr Bluetooth subsystem. Rated critical severity (CVSS 9.6), this vul
The documentation specifies that the BT_GATT_PERM_READ_LESC and BT_GATT_PERM_WRITE_LESC defines for a Bluetooth characte
Potential buffer overflows in the Bluetooth subsystem due to asserts being disabled in /subsys/bluetooth/host/hci_core.c
EUVD-2026-107485
NVD
CVE.org
EPSS
GitHub
VulDB
Exploit-DB