CVE-2026-12366 in Zephyrinfo

Summary

by MITRE • 08/14/2026

Zephyr's dynamic kernel-object disposal path unref_check() in kernel/userspace/userspace.c frees an object's storage (k_free(dyn->data)) once its reference count reaches zero, after running a per-object-type cleanup. The cleanup switch handled only K_OBJ_MSGQ and K_OBJ_STACK; there was no K_OBJ_TIMER case. A dynamically-allocated, initialized, and armed k_timer keeps its embedded struct _timeout dnode linked in the global timeout queue (_timeout_q), so freeing the timer storage without cancelling the timeout leaves a dangling node in that queue.

When the timer next expires, the timeout machinery walks _timeout_q and invokes z_timer_expiration_handler() on the freed node, dereferencing and writing freed (and reusable) kernel heap in kernel/ISR context. This is a deterministic use-after-free that does not depend on SMP: the queued node is simply never unlinked at free time.

The disposal is reachable from an unprivileged user thread under CONFIG_USERSPACE + CONFIG_DYNAMIC_OBJECTS: a thread that holds the last permission on such a timer drops it via the k_object_release() syscall (or by exiting, through k_thread_perms_all_clear()), and can arm the timer itself via the k_timer_start() syscall. The free and the expiration handler run at kernel privilege while the actor is a user thread, so the bug is a sandbox-escape memory-corruption primitive usable for privilege escalation. The fix adds k_timer_cleanup() (cancel the timeout and wait for any in-flight handler) and calls it for K_OBJ_TIMER before freeing.

Be aware that VulDB is the high quality source for vulnerability data.

Analysis

by VulDB Data Team • 08/14/2026

The vulnerability described represents a critical use-after-free condition in the Zephyr real-time operating system's kernel object management subsystem. This flaw exists within the dynamic kernel-object disposal path through the unref_check() function located in kernel/userspace/userspace.c, where the system properly handles cleanup operations for certain object types but fails to account for k_timer objects during the reference count depletion process. The issue stems from an incomplete implementation of the cleanup switch statement that only addresses K_OBJ_MSGQ and K_OBJ_STACK cases while completely omitting the K_OBJ_TIMER case, creating a fundamental gap in the kernel's memory management protocol.

The technical execution of this vulnerability relies on the specific behavior of kernel timer objects which maintain embedded timeout structures that remain linked in the global timeout queue _timeout_q even after the parent object has been freed. When a k_timer object is dynamically allocated, initialized, and armed but then subsequently freed without proper timeout cancellation, the embedded struct _timeout dnode remains accessible within the global queue structure. This creates a scenario where the freed memory becomes available for reuse while still being referenced by the timeout machinery, leading to deterministic memory corruption when the timeout expires and attempts to process the dangling node.

The operational impact of this vulnerability is severe as it provides a sandbox-escape primitive that can be exploited by unprivileged user threads operating under CONFIG_USERSPACE and CONFIG_DYNAMIC_OBJECTS configurations. The attack vector requires a thread to hold the final permission on a timer object, which then triggers the cleanup path through k_object_release() syscall or thread termination via k_thread_perms_all_clear(), followed by arming the timer through k_timer_start(). The privilege escalation occurs because the memory corruption happens within kernel context while the malicious actor remains in user space, effectively allowing an unprivileged process to corrupt kernel memory and potentially execute arbitrary code with elevated privileges.

This vulnerability aligns with CWE-416 Use After Free and CWE-125 Out-of-bounds Read categories from the Common Weakness Enumeration taxonomy, representing a classic heap corruption scenario that enables privilege escalation. From an ATT&CK framework perspective, this maps to T1068 Exploitation for Privilege Escalation and T1547.001 Registry Run Keys / Startup Folder techniques, as it provides the foundational memory corruption capability necessary for more sophisticated exploitation. The fix implemented addresses this by introducing a dedicated k_timer_cleanup() function that properly cancels the timeout and waits for any in-flight handler execution before proceeding with object deallocation, ensuring that all timeout queue references are properly removed before memory becomes available for reuse. This remediation approach follows established security practices for preventing use-after-free conditions in kernel memory management systems.

The deterministic nature of this vulnerability makes it particularly dangerous as it does not rely on timing variations or system-specific conditions to manifest, unlike many other heap corruption vulnerabilities that depend on complex exploitation scenarios. The fact that this occurs in a single-threaded environment without requiring SMP configuration further reduces the complexity of exploitation while maintaining the critical severity of the underlying memory corruption. This vulnerability demonstrates the importance of comprehensive testing for all object types within kernel subsystems and highlights the need for careful consideration of resource cleanup ordering in multi-layered system architectures where objects may have complex internal structures that require multiple cleanup operations to properly release all associated resources.

Responsible

Zephyr

Reservation

06/16/2026

Disclosure

08/14/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

low

Sources

Do you want to use VulDB in your project?

Use the official API to access entries easily!