---
id: "CVE-2026-19809"
page: "https://infrastack.ai/live/CVE-2026-19809"
kind: "vulnerability"
aliases: ["CVE-2026-19809"]
title: "Zephyr: charger property syscall leaks kernel stack bytes to user threads"
severity: "low"
cvss: 3.3
epss: null
exploited: false
status: "open"
category: "runtime"
products: []
ecosystems: []
tags: ["charger-driver", "embedded", "runtime", "user-mode", "zephyr"]
not_affected_if: ["no-charger-driver", "no-user-threads-with-charger-access", "no-userspace"]
published_at: "2026-11-12T16:19:08+00:00"
first_seen_at: "2026-11-12T16:44:02+00:00"
updated_at: "2026-11-12T16:45:46+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-19809", "first_seen_at": "2026-11-12T16:44:02+00:00"}]
exploit_sources: []
---

# Zephyr: charger property syscall leaks kernel stack bytes to user threads

Link for people: https://infrastack.ai/live/CVE-2026-19809 (this .md is for agents)

The Zephyr charger driver's user-mode syscall copies an uninitialized kernel-stack union back to the calling thread. An unprivileged thread with access to a charger device can read leftover supervisor-stack bytes, which may include kernel addresses.

_Summary, check and fix written by a model from the sources; labelled as such._

## How to check

- Check whether the build sets `CONFIG_USERSPACE=y` and enables a charger driver.
- Check whether the Zephyr tree includes commit `5054384e983c` and commit `c31cac727d02`.
- Confirm the running Zephyr version against the fixed versions in the product ranges, which the sources do not list.

## Fix

- Zephyr: apply commits `5054384e983c` and `c31cac727d02`; both are needed. Fixed release version: unknown.

## Timeline

- 2026-11-12T16:44:02+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-19809

## Documents

- [advisory] Vendor advisory: github.com https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-rghm-r3c9-92qc
- [fix] Patch: github.com https://github.com/zephyrproject-rtos/zephyr/commit/5054384e983c105b90d704272abcd479486ae3a2
- [fix] Patch: github.com https://github.com/zephyrproject-rtos/zephyr/commit/c31cac727d029f273a67f65941985696f1882867

## From the sources

The user-mode system call verifier z_vrfy_charger_get_prop() in drivers/charger/charger_handlers.c declares an uninitialized union charger_propval k_val on the kernel (privileged) stack, passes it to the charger driver back end via z_impl_charger_get_prop(), and then copies the full sizeof(union charger_propval) back into the calling user thread's buffer with k_usermode_to_copy(). That discloses kernel stack contents on two paths:

On error. The copy-out ignores the driver's return code. In-tree back ends return an error without writing through the value pointer for properties they do not implement: charger_gpio_get_prop() returns -ENOTSUP unconditionally, and bq24190_get_prop() has a default: return -ENOTSUP; arm that never touches val. The whole union is then stack residue.
On success. A back end writes only the one union member the requested property selects (for example sbs_charger.c writes the one-byte val->present for CHARGER_PROP_PRESENT and returns 0), yet the handler still copies the whole union, so every byte beyond that member is uninitialized.

The handler is compiled only when CONFIG_USERSPACE=y and is reachable by any user-mode thread that has been granted access to a charger device object. K_SYSCALL_DRIVER_CHARGER() validates only the device object and its API pointer, not the property identifier, so an unprivileged thread can choose prop freely: an unimplemented property forces the error path, a narrow one the success path, and the call can be repeated at will.

Each call discloses up to the size of the union (12 bytes on a 32-bit target, 16 bytes on 64-bit targets where the function-pointer members widen it) of supervisor-stack memory. The bytes are residue of earlier kernel-side frames on the thread's privileged stack and can contain kernel object addresses and saved return addresses, which an unprivileged thread cannot otherwise observe and which help defeat address-layout assumptions when exploiting a separate memory-safety defect. There is no integrity or availability impact.

Two commits fix it, and both are needed. 5054384e983c skips the copy-out when the back end reports an error. c31cac727d02 zeroes the union before the driver call, so the bytes copied out on success are driver-written data or zeros. A tree carrying only the first still leaks on every successful call.

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
