Zephyr RTOS: NULL function pointer call in UART wide-data syscall verifiers
Summary
The user-mode syscall verifiers for the 16-bit (wide data) UART API check the wrong driver operation, the 8-bit op instead of the 16-bit op that is later called. A user-mode thread that holds access to a UART device object can invoke these syscalls and trigger an indirect call through a NULL function pointer in kernel mode. The result is a kernel fault that, with the default fatal error handler, halts or reboots the system.
Affected
- Zephyr 3.0.0 to before 4.3.2
- Zephyr 4.4.0 to before 4.5.0
- Requires CONFIG_USERSPACE and CONFIG_UART_WIDE_DATA; CONFIG_UART_ASYNC_API for the tx and rx_enable variants
- Not affected: Zephyr versions before 3.0.0 and default builds without the wide-data option
Fixed in
- Zephyr 4.3.2
- Zephyr 4.5.0
- Backport to the 4.4 branch in PR #119388; the exact 4.4.x release is unknown.
Workaround
- No vendor workaround documented.
- Disabling CONFIG_UART_WIDE_DATA removes the exposure if the 16-bit UART API is not used (not a vendor statement; test before changing production builds).
- Restrict which user-mode threads can access UART device objects.
Exploitation
- No public exploit code known; not listed in CISA KEV (per secondary sources).
- The bug report has been public on GitHub since September 2026.
- Impact is denial of service only; no code execution or data disclosure.
Our recommendation
- Check whether your devices or firmware are built with Zephyr and with CONFIG_USERSPACE and CONFIG_UART_WIDE_DATA enabled.
- Ask device vendors whether their firmware is affected and which Zephyr version they use.
- Plan the firmware update to 4.3.2, 4.4.x with the backport, or 4.5.0 for devices where availability matters.
- Monitor vendor advisories for updates.
Public exploits
PoC-in-GitHub, Metasploit and Exploit-DB list nothing for this CVE.
Research sources
- GitHub Security Advisory GHSA-xvwx-ww79-r346 github.com
- Fix commit 3c13bfd3d3ccdceeb51b884fed5a8d2a49475484 github.com
- Backport pull request #119388 (v4.4 branch) github.com
- Bug report issue #119386 github.com
- CVE record summary (threatint) cve.threatint.com
Researched and written up in English and German by an AI (Claude by Anthropic) based on NVD, CISA, EPSS and the sources listed. The vendor information is authoritative. Researched on 11 Nov 2026, 16:07.
Original description (NVD)
The user-mode syscall verifiers for the 16-bit ("wide data") UART API in drivers/serial/uart_handlers.c validated the wrong driver operation. z_vrfy_uart_poll_out_u16(), z_vrfy_uart_tx_u16() and z_vrfy_uart_rx_enable_u16() each ran K_SYSCALL_DRIVER_UART() against the 8-bit op (poll_out, tx, rx_enable) rather than the 16-bit op that the corresponding implementation dereferences (poll_out_u16, tx_u16, rx_enable_u16). z_impl_uart_poll_out_u16(), z_impl_uart_tx_u16() and z_impl_uart_rx_enable_u16() in include/zephyr/drivers/uart/uart_internal.h call their op unconditionally, with no NULL guard of their own, because the verifier is supposed to have established that the op exists. CONFIG_UART_WIDE_DATA is an application-selectable option that no driver selects, and only a handful of the serial drivers in the tree implement any _u16 operation; every other driver leaves those struct uart_driver_api members NULL while still providing the 8-bit ops the old check inspected. In a build with CONFIG_USERSPACE and CONFIG_UART_WIDE_DATA (plus CONFIG_UART_ASYNC_API for the uart_tx_u16() and uart_rx_enable_u16() variants), an unprivileged user-mode thread that legitimately holds access to such a UART device object can invoke the _u16 syscall: the object, permission and op checks all pass, and the kernel-side implementation then performs an indirect call through a NULL function pointer while running at supervisor privilege. The result is a CPU exception taken in kernel context instead of the intended K_OOPS or -ENOSYS return. With the default k_sys_fatal_error_handler() this halts the system (or warm-reboots it under CONFIG_RESET_ON_FATAL_ERROR), so a thread confined by the userspace sandbox can deny service to the whole device — a capability the user-mode privilege boundary is specifically meant to withhold. The call target is a fixed NULL, so there is no attacker-controlled code execution and no memory disclosure; the separate K_SYSCALL_MEMORY_ARRAY_READ()/K_SYSCALL_MEMORY_ARRAY_WRITE() bounds checks on the caller's buffer were and remain correct. The fix points each verifier at the matching _u16 op, using a plain K_SYSCALL_OBJ() object check where the op does not exist or where the implementation already tests it for NULL.
Sources
The tracker combines official, freely usable data sources – updated continuously:
- NVD (NIST) – CVEs, rating (CVSS), affected products
- CISA KEV – vulnerabilities confirmed by CISA as actively exploited
- CISA Vulnrichment – CISA assessment (SSVC) in the official CVE record
- FIRST EPSS – probability of exploitation
- Microsoft MSRC – Patch Tuesday: vulnerabilities, severity, updates
- PoC-in-GitHub – public proof-of-concept repositories
- Metasploit (Rapid7) – modules of the Metasploit Framework
- Exploit-DB (OffSec) – archive of public exploits (links only)
- Patch days: official vendor pages (linked per vendor) (Vendor patch days)
This product uses data from the NVD API but is not endorsed or certified by the NVD. EPSS data © FIRST.org.
Affected? We can help.
We check whether your systems are affected, install updates and close the gap – continuously with the System Health Checker if you wish.
