[RFC PATCH 0/6] um: introduce pidfd_mmap()/pidfd_munmap() syscalls

Cong Wang posted 6 patches 2 weeks, 1 day ago
arch/um/include/shared/os.h                   |   4 -
arch/um/include/shared/skas/mm_id.h           |   8 +-
arch/um/include/shared/skas/stub-data.h       |  28 --
arch/um/kernel/skas/mmu.c                     |   9 +-
arch/um/kernel/skas/stub.c                    | 151 ++--------
arch/um/kernel/skas/stub_exe.c                |  20 +-
arch/um/os-Linux/skas/mem.c                   | 275 ++----------------
arch/um/os-Linux/skas/process.c               |  92 ++----
arch/um/os-Linux/start_up.c                   |   8 +-
arch/x86/entry/syscalls/syscall_64.tbl        |   2 +
include/linux/syscalls.h                      |   5 +
include/uapi/linux/pidfd.h                    |  18 ++
kernel/pid.c                                  | 132 +++++++++
scripts/syscall.tbl                           |   2 +
tools/testing/selftests/pidfd/Makefile        |   3 +-
tools/testing/selftests/pidfd/pidfd.h         |  34 +++
.../testing/selftests/pidfd/pidfd_mmap_test.c | 234 +++++++++++++++
17 files changed, 520 insertions(+), 505 deletions(-)
create mode 100644 tools/testing/selftests/pidfd/pidfd_mmap_test.c
[RFC PATCH 0/6] um: introduce pidfd_mmap()/pidfd_munmap() syscalls
Posted by Cong Wang 2 weeks, 1 day ago
This RFC adds two syscalls, pidfd_mmap() and pidfd_munmap(), that let a
supervisor install or remove a mapping in another process's address space
without target-side cooperation, and converts User Mode Linux to use them.

  pidfd_mmap(int pidfd, struct pidfd_mmap_args *uargs, unsigned int flags)
  pidfd_munmap(int pidfd, unsigned long addr, unsigned long len)

The backing fd (if any) is resolved in the *caller's* fd table, mirroring
pidfd_getfd()'s cross-task install model. Both are gated by
ptrace_may_access(PTRACE_MODE_ATTACH_REALCREDS); LSM/fsnotify hooks run
against the caller. pidfd_mmap() takes an extensible, size-versioned
argument struct (clone3/openat2 style) since an mmap-shaped call exceeds
the 6-argument syscall limit.

They build on the mm-side remote-install primitives vm_mmap_remote()/
vm_munmap_remote(), posted separately as:

  https://lore.kernel.org/all/20260704231831.354543-2-xiyou.wangcong@gmail.com/

UML is the motivating user. Its SKAS monitor previously installed guest
mappings by driving the stub to execute mmap/munmap itself: in seccomp
mode it passed the physmem fd to the stub over SCM_RIGHTS, and in ptrace
mode it batched STUB_SYSCALL_MMAP/MUNMAP entries for the stub to run.
pidfd_mmap() lets the monitor install mappings into the stub's mm
directly, so the stub never touches the fd or executes mmap/munmap. With
both modes converted, the entire stub-syscall batcher and the SCM_RIGHTS
fd-passing become dead code and are removed (net ~530 lines). The ptrace
conversion (patch 5) is included mainly to demonstrate the primitive's
reach; the security caveats pidfd_mmap() does *not* address (e.g. a guest
blocking SIGALRM to dodge scheduling) are preserved in stub.c.

As this is an RFC, the UML side _intentionally_ does not handle host
portability: it assumes a host kernel that provides pidfd_mmap() and
deliberately omits any detection or fallback for older hosts (which would
otherwise pick the ptrace path, or fail the seccomp probe). That belongs
in a non-RFC version and is left out here to keep the series focused on
demonstrating the impact on UML.

---

Cong Wang (6):
  pidfd: add pidfd_mmap()/pidfd_munmap() syscalls
  um: acquire a stub pidfd via CLONE_PIDFD in seccomp mode
  um: install guest mappings via pidfd_mmap() in seccomp mode
  um: forbid mmap/munmap in the stub seccomp filter
  um: install guest mappings via pidfd_mmap() in both modes
  selftests/pidfd: add pidfd_mmap()/pidfd_munmap() tests

 arch/um/include/shared/os.h                   |   4 -
 arch/um/include/shared/skas/mm_id.h           |   8 +-
 arch/um/include/shared/skas/stub-data.h       |  28 --
 arch/um/kernel/skas/mmu.c                     |   9 +-
 arch/um/kernel/skas/stub.c                    | 151 ++--------
 arch/um/kernel/skas/stub_exe.c                |  20 +-
 arch/um/os-Linux/skas/mem.c                   | 275 ++----------------
 arch/um/os-Linux/skas/process.c               |  92 ++----
 arch/um/os-Linux/start_up.c                   |   8 +-
 arch/x86/entry/syscalls/syscall_64.tbl        |   2 +
 include/linux/syscalls.h                      |   5 +
 include/uapi/linux/pidfd.h                    |  18 ++
 kernel/pid.c                                  | 132 +++++++++
 scripts/syscall.tbl                           |   2 +
 tools/testing/selftests/pidfd/Makefile        |   3 +-
 tools/testing/selftests/pidfd/pidfd.h         |  34 +++
 .../testing/selftests/pidfd/pidfd_mmap_test.c | 234 +++++++++++++++
 17 files changed, 520 insertions(+), 505 deletions(-)
 create mode 100644 tools/testing/selftests/pidfd/pidfd_mmap_test.c


base-commit: 69288464b0af40a988958c0e1b29ff15ccd2acb7
-- 
2.43.0
Re: [RFC PATCH 0/6] um: introduce pidfd_mmap()/pidfd_munmap() syscalls
Posted by Johannes Berg 4 days, 12 hours ago
On Fri, 2026-07-10 at 13:53 -0700, Cong Wang wrote:
> This RFC adds two syscalls, pidfd_mmap() and pidfd_munmap(), that let a
> supervisor install or remove a mapping in another process's address space
> without target-side cooperation, and converts User Mode Linux to use them.

Seems simple enough, but I can't really comment on it.

> As this is an RFC, the UML side _intentionally_ does not handle host
> portability: it assumes a host kernel that provides pidfd_mmap() and
> deliberately omits any detection or fallback for older hosts (which would
> otherwise pick the ptrace path, or fail the seccomp probe). That belongs
> in a non-RFC version and is left out here to keep the series focused on
> demonstrating the impact on UML.

Makes sense for the RFC, but I think the fallback to seccomp as-is might
be useful still, we did see some benefit of seccomp and cannot
necessarily update the host kernels _that_ quickly. Maybe do that only
if forced by the user with seccomp=insecure or something, not pick it
with =auto and fail with seccomp=on if it's not available? That'd be
good enough for us, and not really leave a potential security trap (that
we have now for people who don't read the docs ;) ).

johannes