CVE-2026-58839 AI-generated analysis
platform/system/incremental_delivery, incfs library (MountRegistry mountinfo parsing)
Shrinks the stack-allocated read buffer in the static forEachLine() helper of incfs/MountRegistry.cpp from 128 KiB to 32 KiB, adds a compile-time maxLineLength template parameter with a static_assert against the buffer size, and marks the buffer __attribute__((uninitialized)).
Root cause
forEachLine() in incfs/MountRegistry.cpp declared `char buffer[128 * 1024]` on the stack to pread() the mountinfo file. It is invoked from MountRegistry::Mounts::loadFrom(), which runs from MountRegistry::ensureUpToDate() (called by copyMounts() and reload()) whenever poll() on the mountinfo fd does not return 0, meaning it reports an event or fails. If the calling thread's stack is already close to its limit, a 128 KiB frame can overrun the stack, as stated in the commit message ("may cause stack overflow if we're already nearing the limit").
How the fix works
- incfs/MountRegistry.cpp:forEachLine - kBufSize reduced from 128 * 1024 to 32 * 1024 (and changed from static constexpr to constexpr). The buffer is still a stack array, but its frame cost is a quarter of the previous one.
- incfs/MountRegistry.cpp:forEachLine - new template parameter `size_t maxLineLength` with `static_assert(maxLineLength < kBufSize, ...)`. A caller that declares lines as long as the buffer or longer now fails to compile.
- incfs/MountRegistry.cpp:forEachLine - buffer declared `__attribute__((uninitialized))`, opting out of automatic variable zero-initialization for the 32 KiB array.
- incfs/MountRegistry.cpp:MountRegistry::Mounts::loadFrom - the call site is updated to `forEachLine<maxLineSize>` with `constexpr auto maxLineSize = 3 * PATH_MAX + 1024` (a mountinfo line holds 3 paths plus shorter fields), which satisfies the static_assert.
Completeness
- The fix only reduces the size of the stack frame. The buffer is still an automatic array (32 KiB), so stack usage is lowered, not eliminated. The static_assert message added in the code says a rewrite with a vector would be needed if the line size requirement grows.
- In this commit only forEachLine() and the call site in Mounts::loadFrom() are changed. No other stack buffers are touched.
- The static_assert is a compile-time guard on the declared maximum line length. The diff does not show any new runtime handling for a mountinfo line that exceeds the buffer, so behaviour in that case depends on the rest of the loop, which is not shown.
Behavior changes
- forEachLine() uses a 32 KiB stack buffer instead of 128 KiB, so each pread() call reads at most 32 KiB and large mountinfo files may need more iterations.
- The buffer is no longer subject to automatic variable initialization (__attribute__((uninitialized))).
- forEachLine() now requires an explicit maxLineLength template argument. Callers that request a line length of 32 KiB or more fail at compile time.
Per major
- Android 14: same fix: commit b6d06e7ccfc2 in android-security-14.0.0_r29, same diff (blobs 376eaf2..eaf97dc) as the other branches. 6 of 8 lines of the patched region are present at that tag.
- Android 15: same fix: commit 877702e09486 in android-security-15.0.0_r17, same diff. 6 of 8 lines of the patched region are present.
- Android 16: same fix: commit 67b14f0e00af in android-security-16.0.0_r8, same diff. 6 of 8 lines of the patched region are present.
- Android 17: Not listed by the bulletin, which means not affected per the bulletin. 6 of 8 lines of the patched region are present at android-security-17.0.0_r1. The material shows no fix commit for 17.
Unknowns
- Which process, thread and call chain reach forEachLine() with a nearly exhausted stack, and how that leads to the EoP rating in the bulletin.
- How the existing loop body (not shown in full) handles a single mountinfo line that exceeds the buffer size.
- Whether Mounts::loadFrom() is the only caller of forEachLine() (the full file is not shown).
- Whether this fix was the only change under bug 466091304 (the material shows one commit per branch).
- Why only 6 of 8 lines of the patched region are present at each tag, and how Android 17 relates to the fix.