MEDIUMCVSS v3.1 5.5Vulnerability

CVE-2026-90834

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.

Properties

Severity
MEDIUM
Nvd fetched at
2026-11-10T23:33:48.924589+00:00
Cvss severity
MEDIUM
Cvss score
5.5
Retrieved at
2026-11-10T23:34:23+00:00
Score
5.5
Cvss version
3.1
Last source
NVD
Cve id
CVE-2026-90834
Cvss vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
First seen by Signal
2026-11-10T23:31:41+00:00
Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Published at
2026-11-10T22:21:14.460
Last modified
2026-11-10T22:21:14.570

Related Entities (1)

HAS_WEAKNESS (1)

Related research

Explore deeper with Ninja Signal's threat intelligence graph

CVE-2026-90834 (CVSS v3.1 5.5) — Ninja Signal Threat Intelligence | Ninja Signal