Executive brief
Zephyr RTOS contains a memory safety bug in its dynamic timer object cleanup that allows an unprivileged user-mode thread to trigger a use-after-free vulnerability in kernel code. When a dynamically-allocated timer is freed without properly cancelling its timeout, a stale reference remains in the kernel's timeout queue. When the timer fires, kernel code dereferences and writes to already-freed memory, enabling privilege escalation and arbitrary code execution within the kernel.
Technical details
The vulnerability exists in kernel/userspace/userspace.c's unref_check() function, which frees dynamically-allocated kernel objects when their reference count reaches zero. The cleanup switch statement handled K_OBJ_MSGQ and K_OBJ_STACK but was missing a case for K_OBJ_TIMER. This means k_timer objects are freed without cancelling their embedded _timeout node, which remains linked in the global _timeout_q queue. When the armed timer later expires, z_timer_expiration_handler() walks the queue and dereferences the freed node, writing to freed kernel heap memory in interrupt context. The vulnerability is reachable from unprivileged user code under CONFIG_USERSPACE + CONFIG_DYNAMIC_OBJECTS via the k_object_release() syscall (or thread exit via k_thread_perms_all_clear()); an attacker can arm the timer and release it to trigger the use-after-free. The fix adds k_timer_cleanup() to cancel pending timeouts before freeing timer objects.
Affected products
- Zephyr Project Zephyr <unknown
Timeline
- 2026-08-14: disclosed
- patched: Fix adds k_timer_cleanup() to cancel timeouts before freeing K_OBJ_TIMER