CVE-2026-12366High· 8.8▾ TwilightZephyr'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 h…
▾ Twilight zone — High severity, or a signal on a lesser flaw
impact 48.4 · likelihood 0 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Stakeholder-Specific Vulnerability Categorization from CISA's ADP record at CVE.org: whether exploitation is observed, whether an attack can be automated, and how much of the system is at stake. The CVSS score shown above comes from the assigning CNA record, not NVD.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via CVEORG
Last analysed / modified upstream
0.2%
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.
zephyr >= 1.12.0 < 4.5.0Refer to the linked advisories for vendor-supplied fixes and affected version ranges.
Connected by shared product, vendor, weakness, or advisory.
CVE-2026-14366Medium· 6.4SiWx91x WiFi driver double-unref / use-after-free of caller-owned TX net_pkt
CVE-2026-85035High· 8.8Use-after-free via dynamically allocated message queue retained by the CAN RX filter
CVE-2026-85032Medium· 4.8Use-after-free in the MCTP over USB binding when the host disables the class while RX parsing is in progress
CVE-2026-82388Medium· 5.3Use of a released HFP HF object after a failed RFCOMM connect in the Bluetooth Classic host
CVE-2026-79979High· 7.8Stale TLB entries after demand-paging page-out let arm64 user threads access reused physical frames
CVE-2026-10655Medium· 6.5Use-after-free race in SNTP async client when closing the socket while the socket service is still polling it