Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-10681

CVE-2026-10681: Zephyr Privilege Escalation Vulnerability

CVE-2026-10681 is a privilege escalation flaw in Zephyr's userspace dynamic-objects subsystem that allows concurrent threads to bypass ACL isolation on SMP systems. This post covers technical details, affected versions, and mitigation.

Published:

CVE-2026-10681 Overview

CVE-2026-10681 is a race condition [CWE-362] in the Zephyr real-time operating system (RTOS) userspace dynamic-objects subsystem. The function thread_idx_alloc() in kernel/userspace/userspace.c allocated a thread permission index from the global _thread_idx_map[] bitmap without holding lists_lock. On symmetric multiprocessing (SMP) systems, two concurrent user-mode threads calling k_object_alloc(K_OBJ_THREAD) can receive the identical tidx. The two threads then alias the same bit position in every kernel object's perms[] bitfield, collapsing access-control list (ACL) isolation between them. The flaw affects every Zephyr release up to and including v4.4.0.

Critical Impact

Two user threads share the same permission index, so any kernel-object access granted to one thread is implicitly granted to the other, defeating userspace ACL isolation.

Affected Products

  • Zephyr RTOS releases from 2018 through v4.4.0 (inclusive)
  • Builds configured with CONFIG_USERSPACE, CONFIG_DYNAMIC_OBJECTS, and CONFIG_SMP
  • Any downstream product embedding a vulnerable Zephyr kernel with userspace enabled on SMP hardware

Discovery Timeline

  • 2026-07-25 - CVE-2026-10681 published to the National Vulnerability Database (NVD)
  • 2026-07-27 - Last updated in NVD database

Technical Details for CVE-2026-10681

Vulnerability Analysis

The defect lives in Zephyr's per-thread permission-index allocator. Each user-mode thread is assigned a unique bit position, which the kernel later uses to index into every kernel object's perms[] bitfield. That bit position gates whether the thread can call syscalls against a given object.

thread_idx_alloc() scanned _thread_idx_map[], called find_lsb_set(), and then performed a non-atomic read-modify-write (RMW) to clear the selected bit. The scan and clear ran without lists_lock held. Two CPUs entering the function simultaneously could both read the same word, both observe the same lowest free bit, and both clear it independently. Both callers then returned the same tidx.

Once two K_OBJ_THREAD objects share a thread_id, they occupy the same slot in every object's permission bitfield. k_object_access_grant() on any kernel object for one thread transparently authorizes the other. A secondary lost-update window exists between the unlocked &= ~BIT() in the allocator and the locked |= BIT() in thread_idx_free(), which can also leak indices from the pool.

Root Cause

The root cause is a missing lock around a shared bitmap RMW. The permission-index allocator was added in 2018 and never acquired lists_lock, while the corresponding free path did. The asymmetry created both a duplicate-allocation race and a lost-update race on the same map.

Attack Vector

Exploitation requires local access on an SMP device running a vulnerable Zephyr image with userspace and dynamic objects enabled. Any user-mode thread can invoke the unrestricted k_object_alloc syscall. Two cooperating user threads pinned to different CPUs can race the allocator to obtain a shared thread_id, then wait for the higher-privileged sibling to be granted access to a kernel object and inherit that access silently.

c
// Zephyr patch: kernel/userspace/userspace.c
// kernel: userspace: fix thread_idx_alloc() for SMP
	int i;
	int idx;
	int base;
+	bool ret = false;
+	k_spinlock_key_t key;

	base = 0;
+	key = k_spin_lock(&lists_lock);
	for (i = 0; i < CONFIG_MAX_THREAD_BYTES; i++) {
		idx = find_lsb_set(_thread_idx_map[i]);

		if (idx != 0) {
+			struct dyn_obj *obj, *next;
+
			*tidx = base + (idx - 1);

			/* Clear the bit. We already know the array index,

Source: Zephyr commit 862ea2fbbeb2ccdf8ff994b03e2e3b4405f2c37d

The patch acquires lists_lock before scanning _thread_idx_map[] and holds it across the bitmap clear and the subsequent perms[] reset. The previously separate object-list traversal is inlined so the lock is held over the full critical section.

Detection Methods for CVE-2026-10681

Indicators of Compromise

  • Two active k_thread structures reporting the same thread_id (permission index) in kernel diagnostics or a debugger view of _thread_idx_map[].
  • User-mode threads successfully performing syscalls against kernel objects for which they were never explicitly granted access.
  • Unexpected -EBUSY or missing-index errors from k_object_alloc() under load, suggesting lost updates in the index pool.

Detection Strategies

  • Audit builds for the vulnerable configuration combination: CONFIG_USERSPACE=y, CONFIG_DYNAMIC_OBJECTS=y, and CONFIG_SMP=y on Zephyr ≤ v4.4.0.
  • Instrument thread_idx_alloc() in test builds to log allocated tidx values and assert uniqueness across concurrent callers.
  • Run stress tests that spawn user threads across all CPUs invoking k_object_alloc(K_OBJ_THREAD) in a tight loop and check for duplicate thread IDs.

Monitoring Recommendations

  • Track firmware and software bill of materials (SBOM) entries for Zephyr versions at or below v4.4.0 across your device fleet.
  • Monitor Zephyr security advisories, specifically GHSA-j693-5rh5-8g8h, for backport and downstream vendor updates.
  • Log unexpected kernel-object access grants or permission-check failures in userspace-enabled builds to surface aliasing behavior.

How to Mitigate CVE-2026-10681

Immediate Actions Required

  • Update Zephyr to a release that includes commit 862ea2fbbeb2ccdf8ff994b03e2e3b4405f2c37d or backport the fix into your downstream tree.
  • Inventory devices running Zephyr with CONFIG_USERSPACE, CONFIG_DYNAMIC_OBJECTS, and CONFIG_SMP all enabled and prioritize them for firmware rebuilds.
  • Rebuild and reflash affected images; a runtime hotfix is not possible for an RTOS kernel defect.

Patch Information

The upstream fix holds lists_lock across both the _thread_idx_map[] RMW and the perms[] clear, and inlines the object-list traversal that previously acquired the lock itself. Apply the fix from the Zephyr commit and consult GHSA-j693-5rh5-8g8h for the advisory record.

Workarounds

  • Disable CONFIG_DYNAMIC_OBJECTS if the application does not require runtime allocation of kernel objects, which removes the vulnerable path.
  • Build in uniprocessor mode by disabling CONFIG_SMP where product requirements allow; the race is not reachable on a single CPU.
  • Restrict which images or partitions can spawn user-mode threads to reduce the number of untrusted callers of k_object_alloc.
bash
# Zephyr build configuration example to eliminate the vulnerable path
# prj.conf
CONFIG_USERSPACE=y
# Remove dynamic kernel object allocation if not required
CONFIG_DYNAMIC_OBJECTS=n
# Or, where feasible, disable SMP to avoid the concurrent RMW race
# CONFIG_SMP=n

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.