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

CVE-2026-19669: Zephyr RTOS Fuel Gauge RCE Vulnerability

CVE-2026-19669 is a remote code execution flaw in Zephyr RTOS fuel gauge syscall handlers that allows attackers to break out of user-mode sandbox into kernel memory. This post explains its technical details, impact, and mitigation steps.

Published:

CVE-2026-19669 Overview

CVE-2026-19669 is an out-of-bounds write vulnerability [CWE-787] in the Zephyr real-time operating system (RTOS). The flaw resides in the user-mode syscall verifiers z_vrfy_fuel_gauge_get_props() and z_vrfy_fuel_gauge_set_props() in drivers/fuel_gauge/fuel_gauge_syscall_handlers.c. Both verifiers declare variable-length arrays (VLAs) sized directly from an unvalidated caller-supplied len argument. A thread running in user mode with CONFIG_USERSPACE enabled can leverage this to displace the supervisor stack and write attacker-controlled data into kernel memory.

Critical Impact

A local user-mode thread can achieve an out-of-bounds write in supervisor context, enabling a sandbox escape that leads to kernel code execution or system crash.

Affected Products

  • Zephyr Project RTOS builds that compile drivers/fuel_gauge/fuel_gauge_syscall_handlers.c with CONFIG_USERSPACE enabled
  • Any downstream firmware exposing the fuel_gauge_get_props() or fuel_gauge_set_props() syscalls to user-mode threads
  • Deployments using default CONFIG_PRIVILEGED_STACK_SIZE of 1024 bytes

Discovery Timeline

  • 2026-10-11 - CVE-2026-19669 published to NVD
  • 2026-10-15 - Last updated in NVD database

Technical Details for CVE-2026-19669

Vulnerability Analysis

The verifiers z_vrfy_fuel_gauge_get_props() and z_vrfy_fuel_gauge_set_props() allocate two VLAs — union fuel_gauge_prop_val k_vals[len] and fuel_gauge_prop_t k_props[len] — on the supervisor stack. The len value is a size_t taken straight from the syscall ABI with no bounds check. These VLAs are allocated before K_SYSCALL_DRIVER_FUEL_GAUGE() runs, so the stack displacement occurs even when the caller lacks fuel-gauge object permission.

The follow-on k_usermode_from_copy() calls validate only that the user source buffer is readable. The kernel destination is sized by the same attacker-chosen len, so no destination bounds check exists. Zephyr does not build with stack-clash probing, which means the arbitrary stack displacement does not fault.

Root Cause

The root cause is unvalidated use of attacker-controlled size data to allocate kernel stack memory and copy user data into it. With CONFIG_PRIVILEGED_STACK_SIZE defaulting to 1024 bytes, a len of roughly 170 exhausts the privileged stack. The len * sizeof() multiplication also lacks overflow checking.

Attack Vector

A local user-mode thread invokes fuel_gauge_get_props() or fuel_gauge_set_props() with a large len. This first displaces the supervisor stack pointer by an arbitrary amount. If the thread holds access to a fuel-gauge device object, the subsequent memcpy writes len * sizeof(union fuel_gauge_prop_val) bytes of attacker-controlled data starting well below the stack base. The stack guard region does not contain the write because the copy begins below the guard and walks upward, corrupting unprotected memory first.

c
					      const fuel_gauge_prop_t *props,
					      union fuel_gauge_prop_val *vals, size_t len)
 {
-	union fuel_gauge_prop_val k_vals[len];
-	fuel_gauge_prop_t k_props[len];
-
 	K_OOPS(K_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property));
 
-	K_OOPS(k_usermode_from_copy(k_vals, vals, len * sizeof(union fuel_gauge_prop_val)));
-	K_OOPS(k_usermode_from_copy(k_props, props, len * sizeof(fuel_gauge_prop_t)));
-
-	int ret = z_impl_fuel_gauge_get_props(dev, k_props, k_vals, len);
+	K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(props, len, sizeof(fuel_gauge_prop_t)));
+	K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(vals, len, sizeof(union fuel_gauge_prop_val)));
 
-	K_OOPS(k_usermode_to_copy(vals, k_vals, len * sizeof(union fuel_gauge_prop_val)));
-
-	return ret;
+	return z_impl_fuel_gauge_get_props(dev, props, vals, len);
 }

Source: Zephyr patch commit 0d65ce46. The fix removes the kernel-side copies and validates the caller's arrays in place using K_SYSCALL_MEMORY_ARRAY_READ() and K_SYSCALL_MEMORY_ARRAY_WRITE(), which also handle the len * size multiplication overflow.

Stop Remote Code Execution Before It Runs

Singularity™ Endpoint detects and blocks exploit attempts at machine speed, including zero-days and novel attack techniques.

Stop Exploit Attempts

Detection Methods for CVE-2026-19669

Indicators of Compromise

  • Unexpected K_OOPS kernel faults originating from z_vrfy_fuel_gauge_get_props() or z_vrfy_fuel_gauge_set_props() stack frames
  • Supervisor-mode crashes or hangs correlated with user-mode threads holding fuel-gauge device permissions
  • Anomalous len arguments in syscall traces targeting fuel-gauge property functions

Detection Strategies

  • Instrument syscall tracing to flag fuel_gauge_get_props or fuel_gauge_set_props calls where len exceeds a reasonable property-count ceiling
  • Review firmware builds for presence of the vulnerable VLA pattern in drivers/fuel_gauge/fuel_gauge_syscall_handlers.c prior to the patch commit
  • Enable kernel coredump collection on target devices to capture evidence of supervisor stack corruption

Monitoring Recommendations

  • Log all fatal kernel exceptions and triage any occurring in fuel-gauge driver context
  • Monitor device-side telemetry for unexpected reboots on hardware that uses Zephyr fuel-gauge drivers
  • Track Zephyr dependency versions in software bill of materials (SBOM) tooling to identify unpatched deployments

How to Mitigate CVE-2026-19669

Immediate Actions Required

  • Apply the upstream fix from Zephyr commit 0d65ce46dda0626164503c50f37e6e1f59d310a9 to all affected firmware builds
  • Audit downstream Zephyr forks for the vulnerable VLA pattern in fuel-gauge syscall handlers
  • Rebuild and reflash deployed devices once the patched Zephyr tree is integrated

Patch Information

The fix is tracked in Zephyr commit 0d65ce46 and documented in GitHub Security Advisory GHSA-6ghg-cmrw-8gw5. The patch replaces the kernel-side VLA allocations and k_usermode_from_copy() calls with in-place validation via K_SYSCALL_MEMORY_ARRAY_READ() and K_SYSCALL_MEMORY_ARRAY_WRITE().

Workarounds

  • Build firmware with CONFIG_USERSPACE=n where user-mode isolation is not required by the application
  • Deny fuel-gauge device object permissions to untrusted user-mode threads via k_object_access_grant() policy review
  • Increase CONFIG_PRIVILEGED_STACK_SIZE as a partial hardening measure, though this does not eliminate the vulnerability
bash
# Fetch the patched Zephyr tree and verify the fix is present
git fetch origin
git checkout 0d65ce46dda0626164503c50f37e6e1f59d310a9 -- \
    drivers/fuel_gauge/fuel_gauge_syscall_handlers.c
grep -n "K_SYSCALL_MEMORY_ARRAY" \
    drivers/fuel_gauge/fuel_gauge_syscall_handlers.c

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

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.