CVE-2026-89836 Overview
CVE-2026-89836 is a race condition in the Linux kernel's Flash-Friendly File System (f2fs) that affects large folio invalidation logic. The flaw resides in f2fs_get_read_data_folio(), which calls f2fs_folio_put() before invoking folio_nr_pages(). Dropping the folio lock and reference before computing the invalidate range opens a window for concurrent truncate or folio split operations to shrink or free the compound folio. The resulting undersized range leaves stale sub-folio entries in mapping->i_pages, producing bad page state and livelocks observed on Android systems running kernel v6.18.
Critical Impact
Local unprivileged users can trigger kernel livelock, corrupted xarray state, and bad page state conditions leading to denial of service and potential memory integrity issues.
Affected Products
- Linux kernel f2fs subsystem (v6.18-based branches, including Android)
- Systems using large folios with f2fs page cache invalidation
- Downstream distributions shipping affected kernel versions
Discovery Timeline
- 2026-09-16 - CVE-2026-89836 published to NVD
- 2026-09-16 - Last updated in NVD database
Technical Details for CVE-2026-89836
Vulnerability Analysis
The defect is a Time-of-Check Time-of-Use (TOCTOU) race in f2fs large folio handling. When f2fs_get_read_data_folio() invalidates a large folio from the page cache, it releases the folio lock and drops the caller reference via f2fs_folio_put() before it reads folio_nr_pages(). Between the unlock and the size query, another thread can truncate the inode or split the compound folio. If the folio shrinks or is freed, the subsequent invalidate range calculation uses an outdated page count. The invalidator then targets fewer pages than actually exist, leaving orphaned sub-folios registered in mapping->i_pages.
The leftover xarray entries later collide with truncate_inode_pages_range() during inode eviction. The observed crash trace shows the livelock originating in xas_load and find_get_entries while walking a corrupted xarray, invoked from f2fs_evict_inode through the iput path. Because folio->mapping no longer matches the mapping being truncated, reclaim and truncate paths hit inconsistent state and trigger bad page reports.
Root Cause
The root cause is an ordering error: reference and lock release precede the folio metadata read. The fix captures nr_pages before dropping the folio reference and lock, ensuring the invalidate range reflects the true compound folio size at the moment of the operation.
Attack Vector
Exploitation requires local access with the ability to perform filesystem operations on an f2fs-backed mount. A concurrent truncate or reclaim workload on files backed by large folios is sufficient to reach the racing window. Successful triggering yields kernel livelock and bad page state, degrading system availability and creating conditions where reclaim operates on freed memory.
// Vulnerable ordering (conceptual, from commit description)
// f2fs_get_read_data_folio():
// f2fs_folio_put(folio); // reference and lock dropped first
// nr = folio_nr_pages(folio); // racy read after put
// invalidate_range(mapping, index, nr);
//
// Fixed ordering:
// nr = folio_nr_pages(folio); // read size while holding reference
// f2fs_folio_put(folio);
// invalidate_range(mapping, index, nr);
See the upstream commits for the authoritative patch content: Kernel Git Commit 0dab7138 and Kernel Git Commit cc34df18.
Detection Methods for CVE-2026-89836
Indicators of Compromise
- Kernel BUG: Bad page state warnings referencing folios with mismatched folio->mapping
- Task hangs or livelocks with stack traces terminating in xas_load, find_get_entries, and truncate_inode_pages_range
- Repeated f2fs_evict_inode invocations that fail to complete on files stored on f2fs mounts
Detection Strategies
- Enable CONFIG_DEBUG_VM and CONFIG_DEBUG_VM_PGFLAGS in test kernels to surface xarray inconsistencies at runtime
- Correlate kernel ring buffer (dmesg) messages mentioning folio and f2fs with process termination or hang events
- Use perf or ftrace on truncate_inode_pages_range and f2fs_get_read_data_folio to identify racing callers on production workloads
Monitoring Recommendations
- Forward /var/log/kern.log and journald kernel entries to a central log platform and alert on Bad page state and soft-lockup messages
- Track availability metrics on hosts using f2fs, watching for stalled I/O threads and rising uninterruptible task counts
- Baseline crash and reboot rates on Android fleets running v6.18 kernels to detect regressions tied to this race
How to Mitigate CVE-2026-89836
Immediate Actions Required
- Apply the upstream f2fs fix that reads folio_nr_pages() before calling f2fs_folio_put() in f2fs_get_read_data_folio()
- Rebuild and redeploy affected v6.18-based kernels, prioritizing Android device kernels and servers running f2fs workloads
- Restrict local shell access on multi-tenant systems until patched kernels are in production
Patch Information
The fix is upstreamed in the mainline Linux kernel tree. Reference the two commits: Kernel Git Commit 0dab7138 and Kernel Git Commit cc34df18. Distributions and Android vendors should backport these commits to any v6.18 stable branch in production.
Workarounds
- Where patching is not immediate, migrate workloads off f2fs to ext4 or xfs to eliminate exposure to the vulnerable code path
- Disable large folio support on f2fs mounts in test environments to reduce race probability while patches roll out
- Limit concurrent truncate-heavy workloads on f2fs volumes on unpatched hosts
# Verify running kernel version and f2fs usage
uname -r
mount -t f2fs
# After deploying the patched kernel, confirm the fix commit is present
git -C /usr/src/linux log --oneline | grep -E '0dab7138|cc34df18'
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

