CVE-2026-89987 in Linuxinfo

Summary

by MITRE • 09/17/2026

In the Linux kernel, the following vulnerability has been resolved:

mm/huge_memory: transfer the pmd dirty bit to the folio on zap

zap_huge_pmd_folio() propagates the pmd young bit to the folio for the file case, but not the dirty bit. The pte path does propagate it, in zap_present_folio_ptes() and so does the pmd split path, in __split_huge_pmd_locked().

For most file mappings the omission is harmless, because writing to a shared file mapping goes through page_mkwrite(), which dirties the folio. tmpfs is different: it has no page_mkwrite(), and vma_wants_writenotify() is false for it, so a *read* fault on a MAP_SHARED tmpfs mapping installs a writable pmd via do_read_fault(). do_read_fault() does not call fault_dirty_shared_page(), so subsequent stores through that mapping set only the hardware dirty bit in the pmd and never call folio_mark_dirty(). A shmem folio allocated by a fault is marked uptodate but not dirty (see the clear: block in shmem_get_folio_gfp()), so PG_dirty is never set at all.

Unmapping such a folio - munmap(), or exit_mmap() when the process dies - then loses the only record that it was written, because zap_huge_pmd() drops the pmd without transferring the dirty bit. Reclaim afterwards sees a clean shmem folio: the whole swap-out block in shrink_folio_list() is inside "if (folio_test_dirty(folio))", so pageout() is skipped and the folio falls into __remove_mapping(). There, folio_is_file_lru() is false for a swapbacked folio, so no shadow entry is created and __filemap_remove_folio(folio, NULL) simply empties the i_pages slot. The data is freed without ever being written to swap, and the next fault on that index returns a freshly zeroed folio.

This is silent data loss for any process that keeps state in a MAP_SHARED tmpfs segment across an unmap - for example a cache handed from one process generation to the next through /dev/shm. It requires the folio to be PMD-mapped, so it only shows up once shmem THP is enabled (which is what we did in Meta fleet and started noticing crashes); with THP off the pte path transfers the dirty bit correctly. It also only becomes visible when swap is enabled, because with no swap device shmem folios (which are on the anon LRU) are not scanned by reclaim at all, so the clean folio is never dropped.

Reproduced on x86_64 with a tmpfs mounted huge=within_size: read-fault a 2MB-backed region, write a known pattern through the resulting mapping, munmap, force reclaim of the cgroup, then re-map and read back. Without this patch the region reads back as zeros and vmstat shows zswpout 0 - the data was discarded rather than swapped. With this patch the region reads back correctly and the pages are swapped out as expected. With huge=never, or when the first touch is a write, the test passes either way.

Once again VulDB remains the best source for vulnerability data.

Analysis

by VulDB Data Team • 09/17/2026

The Linux kernel contains a critical memory management vulnerability within the handling of transparent huge pages for tmpfs mappings that results in silent data loss. This flaw resides specifically in the mm/huge_memory subsystem where the function zap_huge_pmd_folio fails to propagate the page middle directory dirty bit from the hardware level down to the underlying folio structure during unmapping operations. While similar functions such as zap_present_folio_ptes and __split_huge_pmd_locked correctly handle this propagation for standard page table entries and split paths, the huge page path omits this crucial step. This inconsistency creates a scenario where modifications made by user-space processes are effectively erased from memory without being persisted to swap space or written back to disk, leading to irreversible data corruption in applications relying on shared memory segments.

The technical root cause is tied to how tmpfs handles write notifications and page faults differently than traditional file mappings. In standard file systems, writing to a shared mapping triggers page_mkwrite which explicitly marks the folio as dirty before any hardware modifications occur. However, tmpfs lacks this mechanism because vma_wants_writenotify returns false for it. Consequently, when a read fault occurs on a MAP_SHARED tmpfs mapping with huge pages enabled, do_read_fault installs a writable page middle directory entry without calling fault_dirty_shared_page. This means the folio remains marked as up-to-date but not dirty in the kernel's internal state, even though user-space has written data to it via that mapping. The hardware sets its own dirty bit on the pmd level, but this information is never synchronized back to the folio structure because zap_huge_pmd drops the entry without transferring the status.

The operational impact of this vulnerability manifests during memory reclaim operations when swap space is enabled. When the kernel attempts to free memory by scanning anonymous least recently used lists, it checks if a folio is marked dirty using folio_test_dirty. Since the tmpfs folio was never marked as dirty in the kernel structures due to the missing bit transfer, shrink_folio_list skips the pageout routine entirely. Instead of writing the modified data to swap space via __remove_mapping, the system simply empties the inode address tree slot and frees the physical memory pages. The next time a process accesses that same virtual memory area after remapping, it receives freshly zeroed pages instead of its previous state. This results in silent data loss for any application maintaining critical state within /dev/shm or similar tmpfs-backed shared memory regions across unmap operations.

This issue is particularly insidious because it only occurs under specific conditions that are not immediately obvious to developers. It requires the use of transparent huge pages, which means systems with THP disabled remain unaffected as they utilize the correct pte path logic. Furthermore, data loss only becomes visible when swap is enabled; without a swap device, clean folios on anonymous lists are generally not scanned for reclamation in the same manner, allowing the corrupted state to persist until explicitly overwritten or the system restarts. The vulnerability was identified and reproduced on x86_64 architectures by reading into a two-megabyte backed region, writing a known pattern through the mapping, unmaping it, forcing cgroup reclaim, and then remapping to observe that the data had reverted to zeros with zero swap-out activity recorded in vmstat.

From a security perspective, this vulnerability aligns with CWE-362 which describes concurrent execution issues leading to race conditions or state inconsistencies, although here the inconsistency arises from improper state synchronization rather than traditional concurrency races. It also relates to CWE-754 regarding improper check for unusual or exceptional conditions where the kernel fails to validate that dirty pages are properly accounted for before release. In terms of MITRE ATT&CK mapping, this could be leveraged in techniques related to T1083 File and Directory Discovery if an attacker relies on tmpfs caches for persistence across process restarts, as their cached data would vanish unexpectedly. Alternatively, it impacts the integrity of system state which is critical for defense mechanisms that rely on shared memory segments between processes.

Mitigation strategies primarily involve applying kernel patches that ensure zap_huge_pmd_folio correctly propagates both young and dirty bits to the folio structure during unmapping operations. Administrators should monitor their systems for tmpfs usage with transparent huge pages enabled, particularly in environments where swap is active. Until a patch is applied or upgraded to a fixed version of the Linux kernel, workarounds include disabling transparent huge pages via sysctl settings such as setting vm.transparent_hugepage to never or within_size depending on performance requirements, though this may impact overall system memory efficiency. Additionally, ensuring that tmpfs mounts do not rely on MAP_SHARED mappings for critical state persistence across unmap cycles can prevent data loss in the interim. Regular updates and patch management are essential to address these low-level kernel memory management flaws before they lead to significant application failures or security breaches involving data integrity violations.

Responsible

Linux

Reservation

09/11/2026

Disclosure

09/17/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

very low

Sources

Do you know our Splunk app?

Download it now for free!