CVE-2026-10677 Overview
CVE-2026-10677 is a kernel memory leak vulnerability [CWE-401] in the Zephyr real-time operating system (RTOS). The flaw resides in the z_vrfy_k_poll() syscall verifier in kernel/poll.c when CONFIG_USERSPACE is enabled. A local user thread can trigger repeated kernel heap allocations that are never freed, eventually exhausting the shared kernel resource pool and causing a system-level denial of service. The vulnerability affects Zephyr releases from v1.12.0 through v4.4.1, spanning every version since k_poll was first exposed to user mode.
Critical Impact
A local unprivileged user thread can exhaust the kernel heap by repeatedly leaking k_poll_event[] allocations, blocking legitimate kernel allocations such as k_queue nodes, k_msgq buffers, and future k_poll calls.
Affected Products
- Zephyr RTOS v1.12.0 through v4.4.1
- Zephyr-based firmware images built with CONFIG_USERSPACE=y
- Embedded and IoT devices running affected Zephyr releases
Discovery Timeline
- 2026-07-21 - CVE-2026-10677 published to NVD
- 2026-07-22 - Last updated in NVD database
Technical Details for CVE-2026-10677
Vulnerability Analysis
The z_vrfy_k_poll() function acts as the kernel-side verifier for user-mode invocations of k_poll. It allocates a kernel copy of the caller-supplied k_poll_event[] array using z_thread_malloc(), then iterates through each event to validate the object handle against its expected kernel object type.
Before the fix, validation used K_OOPS(K_SYSCALL_OBJ(...)) inline inside the loop. When a handle failed validation, K_OOPS terminated the calling thread immediately without freeing the events_copy buffer. The allocation remained pinned in the kernel resource pool for the lifetime of the pool.
Because newly spawned user threads inherit the parent's resource_pool from kernel/thread.c, an attacker can spawn sacrificial worker threads that each leak one allocation and then die. Repeating this pattern drains the shared kernel heap until legitimate allocations fail across the entire system.
Root Cause
The root cause is a classic missing-cleanup path on an error branch [CWE-401]. K_OOPS performs an unconditional thread kill, bypassing normal function epilogue and any manual k_free() calls. The verifier assumed the fatal-error path was terminal, so no unwind logic freed events_copy prior to thread termination.
Attack Vector
Exploitation requires local code execution as an unprivileged user thread on a Zephyr build with CONFIG_USERSPACE enabled. The attacker calls k_poll() with num_events >= 1 and at least one forged object handle, then spawns additional user threads to repeat the primitive. No network access, elevated privileges, or user interaction is required beyond running code in user mode.
case K_POLL_TYPE_IGNORE:
break;
case K_POLL_TYPE_SIGNAL:
- K_OOPS(K_SYSCALL_OBJ(e->signal, K_OBJ_POLL_SIGNAL));
+ if (K_SYSCALL_OBJ(e->signal, K_OBJ_POLL_SIGNAL)) {
+ goto oops_free;
+ }
break;
case K_POLL_TYPE_SEM_AVAILABLE:
- K_OOPS(K_SYSCALL_OBJ(e->sem, K_OBJ_SEM));
+ if (K_SYSCALL_OBJ(e->sem, K_OBJ_SEM)) {
+ goto oops_free;
+ }
break;
case K_POLL_TYPE_DATA_AVAILABLE:
- K_OOPS(K_SYSCALL_OBJ(e->queue, K_OBJ_QUEUE));
+ if (K_SYSCALL_OBJ(e->queue, K_OBJ_QUEUE)) {
+ goto oops_free;
+ }
break;
case K_POLL_TYPE_MSGQ_DATA_AVAILABLE:
- K_OOPS(K_SYSCALL_OBJ(e->msgq, K_OBJ_MSGQ));
+ if (K_SYSCALL_OBJ(e->msgq, K_OBJ_MSGQ)) {
+ goto oops_free;
+ }
break;
case K_POLL_TYPE_PIPE_DATA_AVAILABLE:
- K_OOPS(K_SYSCALL_OBJ(e->pipe, K_OBJ_PIPE));
+ if (K_SYSCALL_OBJ(e->pipe, K_OBJ_PIPE)) {
+ goto oops_free;
Source: Zephyr GitHub Commit 8dc7a37. The patch replaces each inline K_OOPS with a conditional goto oops_free so the buffer is freed before the thread is killed.
Detection Methods for CVE-2026-10677
Indicators of Compromise
- Repeated K_OOPS fatal thread terminations originating from user threads calling k_poll.
- Sudden failure of kernel allocations from k_queue, k_msgq, or subsequent k_poll calls after user-mode activity.
- Bursts of short-lived user threads inheriting the same parent resource_pool, followed by heap exhaustion errors.
Detection Strategies
- Instrument Zephyr builds to log every K_OOPS event with the offending thread ID and syscall name, then alert on clusters targeting k_poll.
- Track kernel heap free-space telemetry over time and alert on monotonic decreases correlated with user-mode syscall activity.
- Add unit and fuzz tests that pass forged object handles to k_poll and verify heap accounting returns to baseline after the fatal error.
Monitoring Recommendations
- Enable Zephyr's CONFIG_THREAD_ANALYZER and heap tracking options to expose per-pool utilization in production diagnostics.
- Forward device telemetry and crash logs to a central log platform and hunt for repeated syscall verifier failures per device.
- Review firmware inventories to identify all devices running Zephyr versions between v1.12.0 and v4.4.1 with CONFIG_USERSPACE=y.
How to Mitigate CVE-2026-10677
Immediate Actions Required
- Upgrade Zephyr-based firmware to a release containing commit 8dc7a37bc75402a0a3329397887f32f5fb4da3ad and redeploy to all affected devices.
- Audit all product lines for firmware built with CONFIG_USERSPACE=y on affected Zephyr versions and prioritize their patch rollout.
- Restrict which user threads are permitted to invoke k_poll where application design allows.
Patch Information
The fix is published in the Zephyr project as GHSA-r3cc-8wcr-xfj9 and merged via commit 8dc7a37. The patch replaces each inline K_OOPS(K_SYSCALL_OBJ(...)) call inside z_vrfy_k_poll() with a conditional goto oops_free branch that releases the events_copy allocation before terminating the calling thread. Vendors integrating Zephyr should cherry-pick this commit into any long-term-support branch based on v1.12.0 through v4.4.1.
Workarounds
- Disable CONFIG_USERSPACE on devices where user-mode threads are not required by the application architecture.
- Isolate untrusted workloads into dedicated resource_pool instances so a leak cannot starve system-critical pools.
- Reduce the size of user-thread resource pools to bound the impact of leaked allocations and force earlier failure signals.
# Verify the running Zephyr version and rebuild after applying the patch
west list -f "{name} {revision}" | grep zephyr
cd zephyr && git log --oneline | grep 8dc7a37
west build -b <board> -p always samples/hello_world
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

