Skip to main content

Zephyr RTOS CVE-2026-12365

| EUVDEUVD-2026-58751 MEDIUM
Use After Free (CWE-416)
2026-08-14 vulnerabilities@zephyrproject.org
5.8
CVSS 3.1 · Vendor: zephyrproject
Share

Severity by source

Vendor (zephyrproject) PRIMARY
5.8 MEDIUM
AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:H
vuln.today AI
5.8 MEDIUM

AV:L because k_work is kernel-internal with no syscall; AC:H for the SMP timing race; PR:L for required kernel-mode access; A:H for kernel crash potential.

3.1 AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:H
4.0 AV:L/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:H/SC:N/SI:N/SA:N

Primary rating from Vendor (zephyrproject).

CVSS VectorVendor: zephyrproject

Attack Vector
Local
Attack Complexity
High
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
Low
Availability
High

Lifecycle Timeline

3
Patch available
Aug 14, 2026 - 19:01 EUVD
Source Code Evidence Fetched
Aug 14, 2026 - 18:31 vuln.today
Analysis Generated
Aug 14, 2026 - 18:31 vuln.today

DescriptionCVE.org

A use-after-free exists in the Zephyr second-generation work queue (kernel/work.c) in the handling of delayable work timeouts. When a delayable work item's timeout has been dequeued and its handler work_timeout() is in flight (blocked acquiring the work-queue spinlock), a concurrent cancellation does not wait for that handler to finish. In unschedule_locked() the pre-fix code called z_abort_timeout(), which for an already-announcing record returns -EINVAL without removing it; cancel_async_locked() then observes the work as idle, so even k_work_cancel_delayable_sync() and k_work_flush_delayable() return without blocking on the in-flight handler.

Because those are the APIs the kernel header documents as the safe way to cancel before freeing a k_work_delayable, a caller that frees the object immediately after a successful sync cancel can race the still-pending handler. work_timeout() subsequently dereferences the freed record: it reads to->dticks via z_is_timeout_handler_canceled() and, if the freed slot has been reused so the bail check fails, performs a read-modify-write of wp->flags (K_WORK_DELAYED_BIT) and submits work against a stale dw->queue pointer - a use-after-free read and write.

The k_work API is kernel-mode only (no __syscall entry point), so this is a kernel-internal concurrency defect rather than a userspace privilege escalation. Triggering it requires an SMP build and a subsystem that schedules and then frees (or reschedules) a delayable work item in the narrow window while its timeout is announcing; an attacker able to influence the timing of such teardown (for example via connection churn driving subsystem timers) has a plausible but probabilistic path. The impact is kernel memory corruption or crash (denial of service).

The fix makes unschedule_locked() wait, by spinning on z_try_abort_timeout() returning -EAGAIN while releasing and re-acquiring the work spinlock, until any in-flight handler completes before returning, and switches work_timeout() to atomic K_WORK_DELAYED_BIT ownership. This closes both the free-then-handler use-after-free and the related reschedule early-fire race.

AnalysisAI

Memory corruption and denial of service in Zephyr RTOS's second-generation delayable work queue (kernel/work.c) arise because the documented safe-cancellation APIs-k_work_cancel_delayable_sync() and k_work_flush_delayable()-fail to block until an in-flight timeout handler completes before returning, allowing callers to free a k_work_delayable object that work_timeout() subsequently dereferences. The race exists exclusively in SMP builds; work_timeout() performs a use-after-free read of the freed object's flags and, if the memory slot has been reused so the bail check passes, a use-after-free write to wp->flags and a submit against a stale dw->queue pointer. No public exploit has been identified and the vulnerability is absent from the CISA KEV catalog; exploitation is probabilistic and gated on kernel-mode code execution with influence over subsystem work-item teardown timing.

Technical ContextAI

Zephyr RTOS kernel/work.c implements the second-generation work queue API, providing k_work_delayable objects that combine a timeout record with a deferred execution item. On SMP builds, sys_clock_announce() can dequeue a timeout record and invoke work_timeout() on one CPU while a second CPU concurrently executes a cancellation path. The pre-fix bug stems from CWE-416 (Use After Free): unschedule_locked() called z_abort_timeout(), which returns -EINVAL for an already-announcing timeout without removing it from the in-flight state; cancel_async_locked() then observes the work item as idle and returns, allowing the caller to free the k_work_delayable. The still-executing work_timeout() handler subsequently reads to->dticks via z_is_timeout_handler_canceled(), and if the freed slot has been reallocated so the stale check passes, performs a read-modify-write of wp->flags (K_WORK_DELAYED_BIT) and submits work against dw->queue-both now pointing into freed or reused memory. The fix resolves this by (1) making unschedule_locked() spin on z_try_abort_timeout() returning -EAGAIN, releasing and re-acquiring the work spinlock each iteration until the handler finishes, and (2) switching work_timeout() to atomic K_WORK_DELAYED_BIT ownership via flag_test_and_clear(), so whichever side clears the bit first owns the outcome and the loser bails cleanly.

RemediationAI

Apply upstream commit 59cf34bf212eeb5c7ea88b97e15842b1e7c1a6b7 from https://github.com/zephyrproject-rtos/zephyr/commit/59cf34bf212eeb5c7ea88b97e15842b1e7c1a6b7, which patches unschedule_locked() to spin-wait until any in-flight timeout handler completes and switches work_timeout() to atomic bit-ownership semantics. A patched tagged release version is not independently confirmed from available data-integrators should apply the commit directly to their vendor tree and track the next upstream release. The advisory at https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rhmh-r93p-6g99 should be monitored for version disclosures. If patching is not immediately possible and the product exposes subsystems (e.g., TCP/IP stack, BLE host) that schedule and promptly cancel delayable work objects under external stimulus, a compensating control is to rate-limit or disable the triggering subsystem feature-for example, restricting connection acceptance rates to reduce timer pressure; the trade-off is reduced throughput or availability of that subsystem feature. This is the only practical compensating control, as the race is inherent to the API contract and cannot be addressed via configuration alone.

Share

CVE-2026-12365 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy