Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [SECURITY] mm/userfaultfd: cross-inode page cache injection via mfill_copy_folio_retry()
@ 2026-05-02  8:20 Anindya Roy
  2026-05-02  9:40 ` Andrew Morton
  0 siblings, 1 reply; 5+ messages in thread
From: Anindya Roy @ 2026-05-02  8:20 UTC (permalink / raw)
  To: akpm, rppt, david; +Cc: ljs, security, linux-mm, lokeshgidra

[-- Attachment #1: Type: text/plain, Size: 3432 bytes --]

Hello,

I would like to report a vulnerability in the Linux kernel userfaultfd
implementation that allows cross-inode page cache injection due to VMA
replacement during the UFFDIO_COPY retry path.

*Summary:*

A local unprivileged attacker can inject controlled data into the page
cache of a different shmem/memfd/tmpfs inode than originally targeted.

This occurs because mfill_copy_folio_retry() drops all locks, allowing the
destination VMA to be replaced, but does not verify that the underlying
file (vm_file) remains the same when execution resumes.

As a result, a folio allocated for one inode can be inserted into another
inode’s page cache.

*Affected component:*

File: mm/userfaultfd.c
Function: mfill_copy_folio_retry()

*Affected versions:*

Introduced by: f5f035a72423
Incomplete fix: 292411fda25b
Tested on:
- Ubuntu 6.17.0-23-generic (x86_64)
- Debian 6.1.159-1

The issue appears present in the current mainline at the time of testing.

*Root cause:*

During UFFDIO_COPY:

   1. A folio is allocated based on the original VMA (inode A)
   2. mfill_copy_folio_retry() drops all locks
   3. While locks are dropped, another thread replaces the VMA using
   mmap(MAP_FIXED) with a different file (inode B)
   4. After re-acquiring the VMA, no validation ensures that vm_file is
   unchanged
   5. The previously allocated folio is inserted into inode B’s page cache

The existing fix (292411fda25b) compares vma_uffd_ops(), which is
insufficient because different shmem mappings share the same ops pointer.

*Impact:*

This provides a deterministic primitive:

   - Arbitrary page cache write into shmem/tmpfs files
   - Full control over contents (PAGE_SIZE per injection)
   - No timing race required
   - Works as an unprivileged user (userfaultfd or via user namespace)

Security implications include:

   - Container escape via shared tmpfs (e.g. /dev/shm) in misconfigured
   environments
   - Bypass of memfd seals (F_SEAL_WRITE not enforced in this path)
   - Corruption of shared memory used by privileged processes
   - Enabling privilege escalation chains

*Reproduction:*

The issue is deterministic and can be reproduced as follows:

   1. Map a shmem/memfd file (fd_A) and register userfaultfd
   2. Trigger UFFDIO_COPY with a faulting source buffer
   3. During retry, replace the destination VMA with a mapping of a
   different file (fd_B)
   4. Resume execution and observe injected data in fd_B’s page cache

*Proposed fix:*

Validate that the VMA still maps the same file after retry:

if (state->vma->vm_file != orig_file)
return -EAGAIN;

Additionally, shmem_mfill_filemap_add() should enforce memfd seals (e.g.
reject when F_SEAL_WRITE or F_SEAL_FUTURE_WRITE is set).

*Notes:*

   - The issue is deterministic and reproducible in a single attempt
   - No timing race is required
   - It breaks isolation between independent shmem inodes

For demonstration, I can provide a proof-of-concept that shows one possible
exploitation path: a privileged process reading commands from a /dev/shm
file can be influenced via injected page cache contents, leading to
unintended command execution.

This demonstrates exploitability, but is not required to trigger the
underlying vulnerability.

Please let me know if further details are needed.

Best regards,
Andy
https://github.com/theteatoast

[-- Attachment #2: Type: text/html, Size: 4153 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-05-04 12:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-02  8:20 [SECURITY] mm/userfaultfd: cross-inode page cache injection via mfill_copy_folio_retry() Anindya Roy
2026-05-02  9:40 ` Andrew Morton
2026-05-02 10:15   ` Anindya Roy
2026-05-02 19:26   ` Mike Rapoport
2026-05-04 12:53     ` Anindya Roy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox