Cloudanix VulnDB

CVE-2026-31648

High · 7.8

CVSS

7.8

EPSS

0.2%

Published

Apr 24, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in the Linux operating system can let someone who can already run code on a machine crash it or potentially take control of it, so affected systems should be updated and rebooted.

Exploitation
Local Privilege
Attacker needs
Local User
Complexity
Moderate
Impact
Privilege Gain
Component
OS kernel
Class
Other
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

This Linux kernel memory-management flaw is an integer underflow/overflow condition in filemap_map_pages() during fault-around mapping of file-backed pages. A race between mapping a large folio and a concurrent file-size shrink can cause the kernel to calculate an invalid nr_pages value and map beyond the bounds of the folio. That can corrupt page metadata such as mapcount/reference-count state for pages outside the intended folio, leading to kernel memory corruption, crashes, and potentially local privilege escalation. The CVSS vector indicates local access with low complexity and low privileges required, no user interaction, and high confidentiality, integrity, and availability impact.

Why it matters to the business

Successful exploitation can allow a low-privileged local user or compromised workload to destabilize a Linux host, crash the kernel, corrupt memory, or potentially gain elevated privileges. This is most relevant to multi-user Linux systems, container hosts, build servers, shared compute platforms, and environments where untrusted users or workloads can execute local code. It is not listed in CISA KEV, has no known ransomware use, no reported public exploit maturity, and has a low EPSS score that has remained flat over 30 days, so broad internet-scale exploitation is not currently indicated; however, kernel local privilege escalation bugs can become high priority quickly once exploit code appears.

How an attack unfolds

An attacker first needs the ability to run code locally on an affected Linux system. They would trigger repeated file-backed memory mappings while concurrently causing file-size changes, such as truncation or setattr operations, to win the race between filemap_map_pages() selecting a folio and later recalculating the file end. If the race is won, the kernel may compute an overflowing nr_pages value and attempt to install page table mappings beyond the large folio's actual size. This can corrupt adjacent page metadata and produce warnings such as Bad page state, nonzero mapcount with zero refcount, or faults in folio_add_file_rmap_ptes(), set_pte_range(), and filemap_map_pages(). A reliable exploit would attempt to shape memory layout and repeated race timing to convert this corruption into privilege escalation; less controlled triggering may simply crash the system.

How to fix it

Upgrade to a Linux kernel release that includes the upstream fix moving the end_pgoff calculation before next_uptodate_folio() in filemap_map_pages(), or apply the vendor backport for the affected distribution kernel. Because no product-specific fixed versions were provided, use the relevant Linux distribution advisory and kernel package changelog to identify the corrected kernel build for each platform. After updating, reboot into the patched kernel and remove or de-prioritize boot entries for vulnerable kernels where operationally feasible. If immediate patching is not possible, reduce exposure by limiting local shell access, restricting untrusted workloads, hardening container escape paths, disabling or limiting unprivileged user namespaces where feasible, enforcing least privilege, and monitoring for kernel crash signatures. These mitigations reduce exploit opportunity but do not correct the underlying kernel memory corruption flaw.

How to confirm the fix worked

Confirm the running kernel, not just the installed package, has been updated by checking uname -a or equivalent fleet inventory after reboot. Validate against the Linux distribution security advisory or kernel changelog for the fix to filemap_map_pages() / nr_pages calculation overflow. Review /boot and package-manager state to ensure systems are not still booting vulnerable kernels. Where source validation is used, confirm the kernel contains the change that calculates end_pgoff before next_uptodate_folio() in mm/filemap.c. Operational validation should include checking that no new kernel logs show Bad page state, VM_WARN_ON_FOLIO, folio_add_file_rmap_ptes(), set_pte_range(), or filemap_map_pages() warnings under normal workload. Avoid running proof-of-concept stress tests on production systems because failed attempts may crash the host.

Typical attack path

  1. Gain local code execution as an unprivileged user or inside a workload/container that can exercise file-backed mmap behavior.
  2. Create or access files on a filesystem that supports the relevant file-backed page-cache behavior, such as common Linux filesystems using large folios.
  3. Repeatedly mmap file ranges while another thread or process shrinks/truncates the same file or changes inode size.
  4. Race the kernel so filemap_map_pages() works with a folio selected under one file size but calculates the mapping range after a smaller file size is visible.
  5. Trigger nr_pages overflow/underflow and force set_pte_range() or related routines to map beyond the large folio boundary.
  6. Cause kernel page metadata corruption, leading to a crash or, with exploit engineering, potential privilege escalation.

How to detect it

Detection should focus on evidence of attempted triggering and resulting kernel memory corruption because no network indicator is expected for this local vulnerability. Review kernel logs from journald, dmesg, /var/log/kern.log, /var/log/messages, crash dumps, pstore, kdump/vmcore, and EDR telemetry for page-cache, folio, and page-state warnings. Look for kernel messages mentioning Bad page state, nonzero mapcount, refcount:0 with mapcount:1, VM_WARN_ON_FOLIO, folio_add_file_rmap_ptes, set_pte_range, filemap_map_folio_range, filemap_map_pages, do_fault_around, ext4_setattr, truncate_pagecache, and stress-style mmap/truncation activity. Correlate such events with local process execution, recently created mmap/truncate stress tools, suspicious binaries in temporary directories, abnormal fork/thread bursts, and privilege changes shortly after kernel warnings. Because the issue is local, also examine auditd, process accounting, shell history where available, container runtime logs, and EDR process trees for untrusted users repeatedly invoking mmap-heavy, mlock-heavy, truncate-heavy, or stress-ng-like workloads. A kernel panic or reboot preceded by these log patterns on an unpatched kernel should be investigated as possible exploitation even if no stable privilege escalation artifact is found.

  • Bad page state
  • nonzero mapcount
  • refcount:0 mapcount:1
  • VM_WARN_ON_FOLIO
  • folio_add_file_rmap_ptes
  • set_pte_range
  • filemap_map_folio_range
  • filemap_map_pages
  • do_fault_around
  • next_uptodate_folio
  • truncate_pagecache
  • ext4_setattr
  • stress-ng-mmaptorture
  • stress-ng-mlock
  • stress-ng-env
  • page dumped because: nonzero mapcount
  • page dumped because: VM_WARN_ON_FOLIO
  • BUG: Bad page state in process
  • WARNING: ./include/linux/rmap.h

What your security team should do

  • Prioritize patching shared, multi-tenant, developer, CI/CD, container-host, VDI, HPC, and internet-facing service hosts where local code execution by lower-privileged users is plausible.
  • Inventory Linux kernel versions across the fleet and map them to vendor advisories because fixed package versions vary by distribution and no universal fixed version was provided.
  • Schedule reboots after kernel updates and verify the active running kernel is the patched one.
  • Monitor for kernel log signatures associated with this bug, especially Bad page state, nonzero mapcount, VM_WARN_ON_FOLIO, folio_add_file_rmap_ptes, set_pte_range, and filemap_map_pages.
  • Treat unexplained kernel crashes or page-state corruption on affected kernels as potential exploitation or attempted exploitation, particularly on systems allowing untrusted local workloads.
  • Until patched, limit local interactive access, constrain untrusted containers, disable unprivileged user namespaces where feasible, and apply mandatory access controls such as SELinux or AppArmor.
  • Track exploit maturity and KEV status; reassess urgency if public exploit code, threat actor use, or ransomware adoption emerges.

The record

In the Linux kernel, the following vulnerability has been resolved: mm: filemap: fix nr_pages calculation overflow in filemap_map_pages() When running stress-ng on my Arm64 machine with v7.0-rc3 kernel, I encountered some very strange crash issues showing up as "Bad page state": " [ 734.496287] BUG: Bad page state in process stress-ng-env pfn:415735fb [ 734.496427] page: refcount:0 mapcount:1 mapping:0000000000000000 index:0x4cf316 pfn:0x415735fb [ 734.496434] flags: 0x57fffe000000800(owner_2|node=1|zone=2|lastcpupid=0x3ffff) [ 734.496439] raw: 057fffe000000800 0000000000000000 dead000000000122 0000000000000000 [ 734.496440] raw: 00000000004cf316 0000000000000000 0000000000000000 0000000000000000 [ 734.496442] page dumped because: nonzero mapcount " After analyzing this page’s state, it is hard to understand why the mapcount is not 0 while the refcount is 0, since this page is not where the issue first occurred. By enabling the CONFIG_DEBUG_VM config, I can reproduce the crash as well and captured the first warning where the issue appears: " [ 734.469226] page: refcount:33 mapcount:0 mapping:00000000bef2d187 index:0x81a0 pfn:0x415735c0 [ 734.469304] head: order:5 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 [ 734.469315] memcg:ffff000807a8ec00 [ 734.469320] aops:ext4_da_aops ino:100b6f dentry name(?):"stress-ng-mmaptorture-9397-0-2736200540" [ 734.469335] flags: 0x57fffe400000069(locked|uptodate|lru|head|node=1|zone=2|lastcpupid=0x3ffff) ...... [ 734.469364] page dumped because: VM_WARN_ON_FOLIO((_Generic((page + nr_pages - 1), const struct page *: (const struct folio *)_compound_head(page + nr_pages - 1), struct page *: (struct folio *)_compound_head(page + nr_pages - 1))) != folio) [ 734.469390] ------------[ cut here ]------------ [ 734.469393] WARNING: ./include/linux/rmap.h:351 at folio_add_file_rmap_ptes+0x3b8/0x468, CPU#90: stress-ng-mlock/9430 [ 734.469551] folio_add_file_rmap_ptes+0x3b8/0x468 (P) [ 734.469555] set_pte_range+0xd8/0x2f8 [ 734.469566] filemap_map_folio_range+0x190/0x400 [ 734.469579] filemap_map_pages+0x348/0x638 [ 734.469583] do_fault_around+0x140/0x198 ...... [ 734.469640] el0t_64_sync+0x184/0x188 " The code that triggers the warning is: "VM_WARN_ON_FOLIO(page_folio(page + nr_pages - 1) != folio, folio)", which indicates that set_pte_range() tried to map beyond the large folio’s size. By adding more debug information, I found that 'nr_pages' had overflowed in filemap_map_pages(), causing set_pte_range() to establish mappings for a range exceeding the folio size, potentially corrupting fields of pages that do not belong to this folio (e.g., page->_mapcount). After above analysis, I think the possible race is as follows: CPU 0 CPU 1 filemap_map_pages() ext4_setattr() //get and lock folio with old inode->i_size next_uptodate_folio() ....... //shrink the inode->i_size i_size_write(inode, attr->ia_size); //calculate the end_pgoff with the new inode->i_size file_end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE) - 1; end_pgoff = min(end_pgoff, file_end); ...... //nr_pages can be overflowed, cause xas.xa_index > end_pgoff end = folio_next_index(folio) - 1; nr_pages = min(end, end_pgoff) - xas.xa_index + 1; ...... //map large folio filemap_map_folio_range() ...... //truncate folios truncate_pagecache(inode, inode->i_size); To fix this issue, move the 'end_pgoff' calculation before next_uptodate_folio(), so the retrieved folio stays consistent with the file end to avoid ---truncated---

Affected packages

Ecosystem Package Introduced Fixed
openSUSE:Leap 16.0 dtb-aarch64 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-64kb 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-azure 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-default 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-default-base 0 6.12.0-160000.35.1.160000.2.16
openSUSE:Leap 16.0 kernel-docs 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-kvmsmall 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-obs-build 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-obs-qa 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-rt 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-source 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-syms 0 6.12.0-160000.35.1
openSUSE:Leap 16.0 kernel-zfcpdump 0 6.12.0-160000.35.1

Related vulnerabilities