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

CVE-2026-19184: NXP GAU ADC Driver Privilege Escalation

CVE-2026-19184 is a privilege escalation flaw in the NXP GAU ADC driver that allows user-mode threads to trigger buffer overflows and escalate privileges to kernel mode. This post covers technical details, impact, and mitigation.

Published:

CVE-2026-19184 Overview

CVE-2026-19184 is an out-of-bounds write [CWE-787] in the Zephyr RTOS NXP GAU Analog-to-Digital Converter (ADC) driver (drivers/adc/adc_mcux_gau_adc.c). The driver validates the caller-supplied sequence->buffer_size (bytes) against the number of active channels (sample count), creating a unit mismatch. A user-mode thread holding the ADC device object can submit a half-sized buffer and force the supervisor-mode work-queue handler to write 16-bit ADC conversion results past the buffer boundary. The flaw affects builds compiled with CONFIG_USERSPACE=y on NXP RW61x SoCs with the GAU ADC node enabled.

Critical Impact

An unprivileged local thread can trigger controlled out-of-bounds writes from supervisor context, enabling kernel memory corruption, crashes, or userspace-to-kernel privilege escalation.

Affected Products

  • Zephyr RTOS builds including drivers/adc/adc_mcux_gau_adc.c
  • Deployments on NXP RW61x SoCs with the GAU ADC device node enabled
  • Builds compiled with CONFIG_USERSPACE=y exposing the ADC syscall boundary

Discovery Timeline

  • 2026-10-05 - CVE-2026-19184 published to NVD
  • 2026-10-06 - Last updated in NVD database

Technical Details for CVE-2026-19184

Vulnerability Analysis

The defect originates in how the NXP GAU ADC driver interprets buffer sizing. The driver compares sequence->buffer_size, measured in bytes, against the active channel count, which is a raw sample count. It then stores that byte value directly in data->results_length and uses it in mcux_gau_adc_read_samples() as the number of uint16_t slots available for conversion results.

Because each ADC result occupies sizeof(uint16_t) bytes, a buffer accepted as sufficient can be written with up to twice its size. Every sample past the buffer's midpoint is written out of bounds. When sequence->options->extra_samplings is set, the sampling loop advances the buffer pointer across each iteration, allowing the overrun to reach the full size of the supplied buffer — kilobytes for large extra_samplings values.

Root Cause

The root cause is a byte-versus-element unit confusion in the buffer-size check. The ADC syscall verifier in drivers/adc/adc_handlers.c only confirms the caller owns buffer_size writable bytes using K_SYSCALL_MEMORY_WRITE. Validating sufficiency against the requested channels and extra samplings is delegated to the driver, which performed the comparison in the wrong unit.

Attack Vector

On a kernel built with CONFIG_USERSPACE=y, a user-mode thread granted access to the ADC device object submits a deliberately undersized buffer through adc_read() or adc_read_async(). The driver's work-queue handler executes in supervisor mode outside the caller's Memory Protection Unit (MPU) restrictions. It writes 16-bit ADC results past the buffer boundary at a destination and for a length controlled by the attacker.

The content of the overflowed words is only partially attacker-influenced through selected analog input, gain, and resolution. However, the destination address and overrun length are fully controlled — sufficient for kernel memory corruption or privilege escalation.

The upstream patch replaces the ad-hoc check with the shared adc_sequence_validate_buffer() helper, which validates against num_channels * sizeof(uint16_t). It stores buffer_size / sizeof(uint16_t) in results_length and corrects the loop bound to a post-decrement.

c
 #define ADC_CONTEXT_USES_KERNEL_TIMER
 #include "adc_context.h"
 
+#include "adc_common.h"
+
 #include <fsl_adc.h>
 
 #define NUM_ADC_CHANNELS 16

Source: Zephyr GitHub Commit 82b11958

Detection Methods for CVE-2026-19184

Indicators of Compromise

  • Unexpected kernel panics or MPU faults originating from the ADC work-queue thread on NXP RW61x devices
  • Corrupted kernel data structures adjacent to buffers passed into adc_read() or adc_read_async()
  • Application crashes immediately following ADC sequence submissions with mismatched buffer_size and channel counts

Detection Strategies

  • Audit source code and binaries built with CONFIG_USERSPACE=y for the vulnerable adc_mcux_gau_adc.c path
  • Inspect ADC callers for sequences where buffer_size is less than num_channels * sizeof(uint16_t) * (1 + extra_samplings)
  • Enable Zephyr memory-domain and MPU fault logging to capture out-of-bounds writes from the ADC driver context

Monitoring Recommendations

  • Collect serial and fault logs from fielded RW61x devices and forward them to a central telemetry pipeline for anomaly review
  • Monitor firmware supply-chain inventories to flag devices still running pre-patch Zephyr versions with the GAU ADC node enabled
  • Track GitHub Security Advisory GHSA-j86w-mfgw-fxj9 for updates and backport status across downstream distributions

How to Mitigate CVE-2026-19184

Immediate Actions Required

  • Apply the upstream Zephyr fix from commit 82b11958065aa85f8644ddc318ff4a328d1443c8 and rebuild affected firmware images
  • Deploy updated firmware to all NXP RW61x deployments that enable the GAU ADC node with CONFIG_USERSPACE=y
  • Review ADC permission grants and remove device-object access from untrusted user-mode threads where possible

Patch Information

The fix is available in the Zephyr Project upstream repository. See the Zephyr GitHub Commit 82b11958 and the GitHub Security Advisory GHSA-j86w-mfgw-fxj9 for full details. The patch adopts adc_sequence_validate_buffer(), stores results length as element count, and corrects the sampling loop bound.

Workarounds

  • Disable CONFIG_USERSPACE on affected builds when the user-mode boundary is not strictly required
  • Remove the GAU ADC device node from the device tree on RW61x targets that do not need the peripheral
  • Enforce in-application validation that ensures buffer_size >= num_channels * sizeof(uint16_t) * (1 + extra_samplings) before calling adc_read()
bash
# Fetch and apply the upstream fix
git fetch origin
git cherry-pick 82b11958065aa85f8644ddc318ff4a328d1443c8
west build -p auto -b rd_rw612_bga samples/drivers/adc

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.