CVE-2026-89987 json
mm/huge_memory: transfer the pmd dirty bit to the folio on zap
published 2026-09-16 53 d ago modified 2026-10-30 9 d ago also EUVD-2026-80595
- cvss
- —
- not scored
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- 0.2%
- EPSS 0.2% chance of exploitation in 30 days, percentile 12%
- public exploits
- 0
- none known
Summary
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.
Patch / fix
- Linux Linux 5.10.273, 5.15.224, 6.1.191, 6.6.160, 6.12.114, 6.18.52, 7.2.5, 7.3
- linux Debian 13 6.12.115-2
- linux Debian 14 7.2.6-1
debian advisories DEBIAN-CVE-2026-89987
- linux Ubuntu 26.04 LTS 7.0.0-42.42
- linux-aws Ubuntu 26.04 LTS 7.0.0-1016.17
- linux-gcp Ubuntu 26.04 LTS 7.0.0-1016.18
- linux-ibm Ubuntu 26.04 LTS 7.0.0-1017.17
- linux-riscv Ubuntu 26.04 LTS 7.0.0-42.42.1
- linux-oracle Ubuntu 26.04 LTS 7.0.0-1015.16
- linux-hwe-7.0 Ubuntu 24.04 LTS 7.0.0-42.42~24.04.1
- linux-oem-7.0 Ubuntu 26.04 LTS 7.0.0-1017.17
ubuntu advisories UBUNTU-CVE-2026-89987
Ubuntu security data © Canonical Ltd., from https://github.com/canonical/ubuntu-security-notices via OSV; changed: normalised to fixed package versions per release. CC BY-SA 4.0
- kernel-rt Real Time Module 15 SP7 6.4.0-150700.7.81.1
- kernel-syms-rt Real Time Module 15 SP7 6.4.0-150700.7.81.1
- kernel-source-rt Real Time Module 15 SP7 6.4.0-150700.7.81.1
- kernel-64kb SLE Module for Basesystem 15 SP7 6.4.0-150700.53.87.3
- kernel-syms SLE Module for Development Tools 15 SP7 6.4.0-150700.53.87.1
- kernel-azure SLE Module for Public Cloud 15 SP7 6.4.0-150700.53.87.3
- kernel-source SLE Module for Development Tools 15 SP7, SLE Module for Basesystem 15 SP7 6.4.0-150700.53.87.3
- kernel-default SLE Workstation Extension 15 SP7, SLE Module for Legacy 15 SP7, SLE Module for Basesystem 15 SP7 +2 more 6.4.0-150700.53.87.3
suse advisories SUSE-SU-2026:4940-1SUSE-SU-2026:4935-1SUSE-SU-2026:4934-1SUSE-SU-2026:24473-1SUSE-SU-2026:24553-1SUSE-SU-2026:24422-1
- kernel-rt openSUSE Leap 16.0 6.12.0-160000.40.1
- dtb-aarch64 openSUSE Leap 16.0 6.12.0-160000.40.1
- kernel-64kb openSUSE Leap 16.0 6.12.0-160000.40.1
- kernel-syms openSUSE Leap 16.0 6.12.0-160000.40.1
- kernel-azure openSUSE Leap 16.0 6.12.0-160000.40.1
- kernel-obs-qa openSUSE Leap 16.0 6.12.0-160000.40.1
- kernel-source openSUSE Leap 16.0 6.12.0-160000.40.1
- kernel-default openSUSE Leap 16.0 6.12.0-160000.40.1
opensuse advisories openSUSE-SU-2026:22167-1openSUSE-SU-2026:11880-1
- kernel Azure Linux 3.0 6.6.161.1-1
azure linux advisories AZL-101499
Azure Linux vulnerability data, Copyright (c) Microsoft Corporation, from https://github.com/microsoft/AzureLinuxVulnerabilityData via OSV, under the MIT licence; changed: normalised to fixed package versions per release. MIT
- git.kernel.org/stable/c/79d8c89baa10612c1675972a632c65cdbe0936f6 commit
- git.kernel.org/stable/c/13f4910d81b62a214cdb28b47237198fa96078a2 commit
- git.kernel.org/stable/c/7a4c3f7b47ba34b021a7747081f330bfb76a4271 commit
- git.kernel.org/stable/c/6e904f9e8cb0e39f60e1cdbea679f89346a563c2 commit
- git.kernel.org/stable/c/fd720d3906877b3d2118cd480027e4bc6648f0c5 commit
- git.kernel.org/stable/c/effe3cc6d4fdd407457eb30f7b0ef094393f0d64 commit
- git.kernel.org/stable/c/9435cddf1378d149d826bd7bd1448a44bf96868d commit
- git.kernel.org/stable/c/fe6cf984939d8e12cb33a99673c8d026c5135e68 commit
Vendor advisories
What the vendors themselves say about their products: affected, fixed or not affected, and what to do.
red hat product security vex CVE-2026-89987 updated cvss 3.6
kernel: mm/huge_memory: transfer the pmd dirty bit to the folio on zap
-
Red Hat Enterprise Linux 8 perf, kernel, bpftool, kernel-rt, kernel-core, kernel-tools, +29 more Red Hat Enterprise Linux 9 rv, perf, rtla, kernel, bpftool, libperf, +83 more Red Hat Enterprise Linux 10 kernel Red Hat OpenShift Container Platform 4 openshift/ose-rhel-coreos-8, openshift/ose-rhel-coreos-9 Red Hat OpenShift Container Platform 5 openshift/ose-rhel-coreos-9affected: workaround, no fix available “Fix deferred”
-
Red Hat Enterprise Linux 6 perf, kernel, python-perf, kernel-kdump, kernel-firmware, kernel-bootwrapper, +1 more Red Hat Enterprise Linux 7 perf, kernel, bpftool, kernel-rt, python-perf, kernel-kdump, +8 morenot affected: vulnerable code not present
Red Hat CSAF VEX © Red Hat, Inc., from https://security.access.redhat.com/data/csaf/v2/vex/; changed: reduced to product statuses and remediations. CC BY 4.0 · csaf
Exploit prediction
0.22% chance of exploitation in the next 30 days, higher than 12% of all scored CVEs (FIRST EPSS, 2026-11-08).
Affected products
- Linux Linux
Classification
- Technology feeds
References
- git.kernel.org /stable/c/79d8c89baa10612c1675972a632c65cdbe0936f6
- git.kernel.org /stable/c/13f4910d81b62a214cdb28b47237198fa96078a2
- git.kernel.org /stable/c/7a4c3f7b47ba34b021a7747081f330bfb76a4271
- git.kernel.org /stable/c/6e904f9e8cb0e39f60e1cdbea679f89346a563c2
- git.kernel.org /stable/c/fd720d3906877b3d2118cd480027e4bc6648f0c5
- git.kernel.org /stable/c/effe3cc6d4fdd407457eb30f7b0ef094393f0d64
- git.kernel.org /stable/c/9435cddf1378d149d826bd7bd1448a44bf96868d
- git.kernel.org /stable/c/fe6cf984939d8e12cb33a99673c8d026c5135e68
Sources
- CVE List CVE-2026-89987
- NVD CVE-2026-89987
Fencer Vulns keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.