CVE-2026-19809: Kernel stack information disclosure in the charger_get_prop() system call handler
The user-mode system call verifier zvrfychargergetprop() in drivers/charger/chargerhandlers.c declares an uninitialized union chargerpropval kval on the kernel (privileged) stack, passes it to the charger driver back end via zimplchargergetprop(), and then copies the full sizeof(union chargerpropval) back into the calling user thread's buffer with kusermodetocopy(). 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: chargergpiogetprop() returns -ENOTSUP unconditionally, and bq24190getprop() 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 sbscharger.c writes the one-byte val->present for CHARGERPROPPRESENT 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 CONFIGUSERSPACE=y and is reachable by any user-mode thread that has been granted access to a charger device object. KSYSCALLDRIVERCHARGER() 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.
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Patch c31cac727d02 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Patch 5054384e983c
Event History
Frequently Asked Questions
Which deployments are exposed?
The affected verifier is compiled only when CONFIG_USERSPACE=y. It is reachable by user-mode threads that have been granted access to a charger device.
What access does an attacker need?
An attacker needs to execute as a user-mode thread and have permission to access the relevant charger device. No user interaction is required, and the issue is locally exploitable.
Do unsupported properties matter, or only successful requests?
Both paths can disclose data. If a driver returns an error without writing the value, the full returned union can contain stack residue; even on success, a driver that initializes only the selected union member can leave the remaining copied bytes uninitialized.