All of lore.kernel.org
 help / color / mirror / Atom feed
From: Justin Suess <utilityemal77@gmail.com>
To: Li Chen <me@linux.beauty>
Cc: "Christian Brauner" <brauner@kernel.org>,
	"Kees Cook" <kees@kernel.org>,
	"Gabriel Krisman Bertazi" <krisman@kernel.org>,
	"Josh Triplett" <josh@joshtriplett.org>,
	"Mateusz Guzik" <mjguzik@gmail.com>,
	"Andy Lutomirski" <luto@kernel.org>,
	"John Ericson" <mail@johnericson.me>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Shuah Khan" <shuah@kernel.org>, "Arnd Bergmann" <arnd@arndb.de>,
	"Oleg Nesterov" <oleg@redhat.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Paul Moore" <paul@paul-moore.com>,
	"Eric Paris" <eparis@redhat.com>,
	"Mickaël Salaün" <mic@digikod.net>,
	"Günther Noack" <gnoack@google.com>,
	"Alexander Viro" <viro@zeniv.linux.org.uk>,
	"Jan Kara" <jack@suse.cz>,
	linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	linux-doc@vger.kernel.org, audit@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-arch@vger.kernel.org, linux-mm@kvack.org
Subject: Re: [RFC PATCH 00/24] pidfd: add a minimal process spawn builder
Date: Tue, 4 Aug 2026 16:25:25 -0400	[thread overview]
Message-ID: <anJE8SfBLtkh6QSa@zenbox> (raw)
In-Reply-To: <cover.1784204592.git.me@linux.beauty>

On Thu, Jul 16, 2026 at 10:31:26PM +0800, Li Chen wrote:
> Hi,
> 
> This RFC follows feedback on my earlier spawn_template RFC [1]. That
> proposal made caching the primary interface; this one starts with general
> process construction. Christian suggested a pidfd/pidfs exec builder
> modeled after fsconfig(), with enough semantics for userspace to implement
> posix_spawn() [2], and Kees agreed [3].
> 
> This RFC is based on linux-next next-20260710 and depends on two pidfs
> fixes that I sent separately:
> 
>   * pidfs: preserve thread pidfds reopened by file handle
>     https://lore.kernel.org/all/20260716052726.1032092-1-me@linux.beauty/
>   * pidfs: handle FS_IOC32_GETVERSION in compat ioctl
>     https://lore.kernel.org/all/20260716052822.1034228-1-me@linux.beauty/
> 
> The initial implementation is source-based. The executable path can be
> provided with the final run request:
> 
>     struct pidfd_spawn_run_args run = {
>         .path = (unsigned long)"/usr/bin/rg",
This should probably be an FD for the path.

This way it prevents race conditions over multiple configuration steps.
>         .argv = (unsigned long)argv,
>         .envp = (unsigned long)envp,
>     };
> 
>     fd = pidfd_open(0, PIDFD_EMPTY);
>     pidfd_spawn_run(fd, &run, sizeof(run));
> 
> Alternatively, the path can be staged before the final run step:
> 
>     struct pidfd_spawn_run_args run = {
>         .argv = (unsigned long)argv,
>         .envp = (unsigned long)envp,
>     };
> 
>     fd = pidfd_open(0, PIDFD_EMPTY);
>     pidfd_config(fd, PIDFD_CONFIG_SET_STRING,
>                  PIDFD_CONFIG_KEY_PATH, "/usr/bin/rg", 0);
Same here. Should probably be an FD to the binary instead.

>     pidfd_spawn_run(fd, &run, sizeof(run));
I'm worried this pidfd_spawn_run just adds another varient to the existing
myriad of exec* syscalls we already have. Would it be better to just have this
work through execveat(fd, "", argv, envp, AT_EMPTY_PATH) instead?

(i.e have execveat take a pidfd directly).

Then you can get rid of pidfd_spawn_run which looks almost structurally
identical to execveat (with the argv and envp collapsed).

Justin
> 
> pidfd_open(0, PIDFD_EMPTY) creates a taskless future pidfd with a stable
> pidfs inode, but no task, PID, or process-count charge. pidfd_spawn_run()
> creates the task and PID; after publication the same fd is the child pidfd,
> and a numeric pidfd resolves to the same inode. Live-task operations return
> -ESRCH before publication. A terminal pre-task failure wakes poll/epoll
> with POLLERR | POLLHUP.
> 
> Source-based mode follows posix_spawn-style defaults. At run time it
> samples the caller's cwd, root, umask, fd table, signal dispositions and
> blocked mask, and namespaces.
> Non-FD_CLOEXEC descriptors remain unless an action changes them; file and
> filesystem state are private child copies before actions. Configuration and
> run stay bound to the creating mm_struct, exact credential object, and
> child PID namespace, so SCM_RIGHTS does not delegate launch authority.
> 
> The first authorized run claims the builder before copying its payload, so
> later failures are terminal. Pre-task failure leaves the fd taskless;
> setup or exec failure leaves it as the child pidfd and exits the child with
> status 127. PIDFD_GET_INFO with PIDFD_INFO_EXIT distinguishes them.
> Success returns the positive child PID in the caller's PID namespace.
> 
> The RFC supports ordered DUP2, CLOSE_RANGE, and FCHDIR actions in
> extensible UAPI records. This exercises child-private fd and cwd setup, but
> is not the complete posix_spawn() action or attribute surface.
> 
> Between task publication and successful exec, the child is explicitly
> embryonic and may not have a valid userspace register frame. Ptrace and
> pidfd_getfd() are denied, procfs treats the PID as absent to other tasks,
> and coredump information reports PIDFD_COREDUMP_SKIP. The child can use its
> own proc entries during executable lookup. Setup runs as initial child task
> work, and successful exec releases this state before exec events are
> published.
> 
> Seccomp sees pidfd_spawn_run(), not separate file-action or exec syscalls,
> and cannot inspect the path or action records behind the run pointer. An
> exec-only denylist that allows unknown syscalls therefore does not block
> this initial exec; policy must filter the builder syscall as a unit. Should
> later expansion provide an immutable restriction profile or action mask
> that seccomp can reason about, or is the coarse syscall boundary
> preferable?
> 
> LSM exec checks and inherited seccomp state remain active. Child setup uses
> a dedicated AUDIT_PIDFD_SPAWN transaction, not a synthetic AUDIT_SYSCALL.
> Should it be selected through the source pidfd_spawn_run() exit rule? An
> existing rule naming only execve() or execveat() does not select it.
> For source/child correlation, could an auxiliary record carry
> the source PID plus the stable pidfs inode? An already traced source is
> rejected before the claim; ptrace auto-attach is not implemented.
> 
> The implementation still uses CLONE_VM | CLONE_VFORK plus exec internally.
> Mateusz suggested that an initial implementation might start with vfork to
> get the API off the ground [4]. That is what this RFC does. It does not yet
> construct a pristine target process without first inheriting source state.
> 
> Missing posix_spawn() pieces include open and close file actions, resetids,
> signal masks/defaults, process groups, sessions, scheduler attributes,
> affinity, cgroup placement, PATH lookup/posix_spawnp(), and exec by fd. The
> RFC also does not include pristine/no-source creation or the executable
> metadata/template cache from my earlier work.
> 
> John Ericson described a real, partially initialized process that remains
> unscheduled while callers install its state, and linked an exploratory
> FreeBSD proc_new()/proc_setfd()/proc_start() refactoring [5]. This RFC
> implements the source-based mode first; a lower-authority pristine/no-source
> mode would be explicit follow-up work.
> 
> Direct process construction is not unprecedented. XNU's posix_spawn path
> does not inherit the parent's address space [6], and Windows
> CreateProcess() accepts explicit startup state [7]. Josh's io_uring_spawn
> LPC slides list "set up process from scratch" as future work and provide
> useful performance context [8]; I am not using those numbers as a claim for
> this RFC.
> 
> If the direction is acceptable, I plan to continue toward:
> 
>   * the complete file-action and attribute set needed by posix_spawn();
>   * pristine target-process construction and an explicit no-source mode;
>   * PATH/posix_spawnp support, if it belongs on the kernel side; and
>   * an optional executable/template layer for workloads such as agent tool
>     calling and compiler drivers.
> 
> The exposed UAPI surface is intentionally limited so the state model and
> kernel/userspace boundary can be reviewed first. If maintainers would
> prefer more posix_spawn semantics or backend work in this RFC, please say
> so and I will adjust the split.
> 
> Codex GPT-5.5 and GPT-5.6-sol provided substantial assistance across design
> conceptualization, implementation, patch splitting, code review, development
> of self-test cases, and test planning and execution.
> 
> Thanks to Christian, Kees, Mateusz, Gabriel, Josh, Andy, John, and others
> for the review and direction.
> 
> [1]: https://patchew.org/linux/20260528095235.2491226-1-me%40linux.beauty/
> [2]: https://lore.kernel.org/all/20260528-madig-fachrichtung-fehlinformation-61117ba640da@brauner/
> [3]: https://lore.kernel.org/all/202606011254.5FCBD65@keescook/
> [4]: https://lore.kernel.org/all/vealb52tv5suireenkke4lul2l3wbnaul2rp3ea545ly5wa5ty@yk3aksvp7skt/
> [5]: https://lore.kernel.org/all/ce71d6df-6851-4e4b-9603-1d55d8d522b8@app.fastmail.com/
> [6]: https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/bsd/kern/kern_exec.c#L4039
> [7]: https://learn.microsoft.com/en-us/windows/win32/procthread/creating-processes
> [8]: https://lpc.events/event/16/contributions/1213/attachments/1012/1945/io-uring-spawn.pdf
> 
> 
> Li Chen (24):
>   pidfd: add spawn builder uapi
>   libfs: allow custom validation of stashed inode data
>   pidfs: add taskless future pidfd inodes
>   pidfd: create taskless spawn builders
>   pidfd: add spawn builder path configuration
>   exec: expose execveat internals to process builders
>   fork: expose vfork completion helper
>   pidfs: attach pids to future pidfd files
>   fork: let process builders supply preallocated pids
>   pidfs: publish future pidfd files
>   pidfd: add spawn builder state tracking
>   fork: let kernel callers create embryonic tasks
>   fork: let new tasks start with task work
>   pidfd: create and execute spawn builder tasks
>   fork: keep embryonic tasks hidden until exec completes
>   audit: add pidfd spawn child contexts
>   pidfd: audit child spawn execution
>   pidfd: make spawn builder execution signal-safe
>   file: expose spawn file-action helpers
>   pidfd: add initial spawn file actions
>   pidfd: consume spawn builders on the first run attempt
>   pidfd: expose spawn builder system calls
>   selftests/pidfd: cover pidfd spawn builders
>   Documentation: describe pidfd spawn builders
> 
>  Documentation/userspace-api/index.rst         |    1 +
>  Documentation/userspace-api/pidfd_spawn.rst   |  247 ++++
>  MAINTAINERS                                   |    6 +
>  arch/alpha/kernel/syscalls/syscall.tbl        |    2 +
>  arch/arm/tools/syscall.tbl                    |    2 +
>  arch/arm64/tools/syscall_32.tbl               |    2 +
>  arch/m68k/kernel/syscalls/syscall.tbl         |    2 +
>  arch/microblaze/kernel/syscalls/syscall.tbl   |    2 +
>  arch/mips/kernel/syscalls/syscall_n32.tbl     |    2 +
>  arch/mips/kernel/syscalls/syscall_n64.tbl     |    2 +
>  arch/mips/kernel/syscalls/syscall_o32.tbl     |    2 +
>  arch/parisc/kernel/syscalls/syscall.tbl       |    2 +
>  arch/powerpc/kernel/syscalls/syscall.tbl      |    2 +
>  arch/s390/kernel/syscalls/syscall.tbl         |    2 +
>  arch/sh/kernel/syscalls/syscall.tbl           |    2 +
>  arch/sparc/kernel/syscalls/syscall.tbl        |    2 +
>  arch/x86/entry/syscalls/syscall_32.tbl        |    2 +
>  arch/x86/entry/syscalls/syscall_64.tbl        |    2 +
>  arch/xtensa/kernel/syscalls/syscall.tbl       |    2 +
>  fs/Makefile                                   |    2 +-
>  fs/coredump.c                                 |    4 +-
>  fs/exec.c                                     |   30 +-
>  fs/exec_internal.h                            |   40 +
>  fs/file.c                                     |   11 +-
>  fs/internal.h                                 |    3 +
>  fs/libfs.c                                    |    5 +-
>  fs/open.c                                     |    7 +-
>  fs/pidfd_spawn.c                              | 1095 +++++++++++++++
>  fs/pidfs.c                                    |  478 ++++++-
>  fs/proc/base.c                                |   11 +-
>  fs/proc/internal.h                            |   18 +-
>  include/linux/audit.h                         |   31 +
>  include/linux/pid.h                           |   13 +
>  include/linux/pidfd_spawn.h                   |    9 +
>  include/linux/pidfs.h                         |   28 +
>  include/linux/sched.h                         |   21 +
>  include/linux/sched/task.h                    |    6 +
>  include/linux/syscalls.h                      |    7 +
>  include/uapi/asm-generic/unistd.h             |    8 +-
>  include/uapi/linux/audit.h                    |    1 +
>  include/uapi/linux/pidfd.h                    |    1 +
>  include/uapi/linux/pidfd_spawn.h              |   49 +
>  kernel/audit.h                                |    1 +
>  kernel/auditsc.c                              |  105 +-
>  kernel/fork.c                                 |   26 +-
>  kernel/nsproxy.c                              |   11 +-
>  kernel/pid.c                                  |   41 +-
>  kernel/ptrace.c                               |    4 +
>  kernel/signal.c                               |    2 +-
>  scripts/syscall.tbl                           |    2 +
>  tools/include/uapi/asm-generic/unistd.h       |    8 +-
>  tools/include/uapi/linux/pidfd_spawn.h        |   49 +
>  .../arch/alpha/entry/syscalls/syscall.tbl     |    2 +
>  .../perf/arch/arm/entry/syscalls/syscall.tbl  |    2 +
>  .../arch/arm64/entry/syscalls/syscall_32.tbl  |   11 +
>  .../arch/mips/entry/syscalls/syscall_n64.tbl  |    2 +
>  .../arch/parisc/entry/syscalls/syscall.tbl    |    2 +
>  .../arch/powerpc/entry/syscalls/syscall.tbl   |    2 +
>  .../perf/arch/s390/entry/syscalls/syscall.tbl |    2 +
>  tools/perf/arch/sh/entry/syscalls/syscall.tbl |    2 +
>  .../arch/sparc/entry/syscalls/syscall.tbl     |    2 +
>  .../arch/x86/entry/syscalls/syscall_32.tbl    |    2 +
>  .../arch/x86/entry/syscalls/syscall_64.tbl    |    2 +
>  .../arch/xtensa/entry/syscalls/syscall.tbl    |    2 +
>  tools/scripts/syscall.tbl                     |    2 +
>  tools/testing/selftests/landlock/audit.h      |    6 +-
>  tools/testing/selftests/pidfd/.gitignore      |    9 +
>  tools/testing/selftests/pidfd/Makefile        |   25 +-
>  tools/testing/selftests/pidfd/config          |    6 +
>  .../pidfd/pidfd_spawn_accounting_test.c       |  428 ++++++
>  .../pidfd/pidfd_spawn_actions_test.c          |  474 +++++++
>  .../selftests/pidfd/pidfd_spawn_audit_test.c  |  521 +++++++
>  .../selftests/pidfd/pidfd_spawn_common.c      |  512 +++++++
>  .../selftests/pidfd/pidfd_spawn_common.h      |   59 +
>  .../selftests/pidfd/pidfd_spawn_compat.c      |  221 +++
>  .../selftests/pidfd/pidfd_spawn_exec_test.c   |  301 ++++
>  .../selftests/pidfd/pidfd_spawn_policy_test.c |  294 ++++
>  .../selftests/pidfd/pidfd_spawn_race_test.c   |  923 ++++++++++++
>  .../pidfd/pidfd_spawn_security_test.c         | 1242 +++++++++++++++++
>  .../selftests/pidfd/pidfd_spawn_test.c        |  550 ++++++++
>  80 files changed, 7938 insertions(+), 81 deletions(-)
>  create mode 100644 Documentation/userspace-api/pidfd_spawn.rst
>  create mode 100644 fs/exec_internal.h
>  create mode 100644 fs/pidfd_spawn.c
>  create mode 100644 include/linux/pidfd_spawn.h
>  create mode 100644 include/uapi/linux/pidfd_spawn.h
>  create mode 100644 tools/include/uapi/linux/pidfd_spawn.h
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_accounting_test.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_actions_test.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_audit_test.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_common.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_common.h
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_compat.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_exec_test.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_policy_test.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_race_test.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_security_test.c
>  create mode 100644 tools/testing/selftests/pidfd/pidfd_spawn_test.c
> 
> -- 
> 2.52.0
> 

  parent reply	other threads:[~2026-08-04 20:25 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-16 14:31 [RFC PATCH 00/24] pidfd: add a minimal process spawn builder Li Chen
2026-07-16 14:31 ` [RFC PATCH 01/24] pidfd: add spawn builder uapi Li Chen
2026-07-16 14:31 ` [RFC PATCH 02/24] libfs: allow custom validation of stashed inode data Li Chen
2026-07-16 14:31 ` [RFC PATCH 03/24] pidfs: add taskless future pidfd inodes Li Chen
2026-07-16 14:31 ` [RFC PATCH 04/24] pidfd: create taskless spawn builders Li Chen
2026-07-16 14:31 ` [RFC PATCH 05/24] pidfd: add spawn builder path configuration Li Chen
2026-07-16 14:31 ` [RFC PATCH 06/24] exec: expose execveat internals to process builders Li Chen
2026-07-16 14:31 ` [RFC PATCH 07/24] fork: expose vfork completion helper Li Chen
2026-07-16 14:31 ` [RFC PATCH 08/24] pidfs: attach pids to future pidfd files Li Chen
2026-07-16 14:31 ` [RFC PATCH 09/24] fork: let process builders supply preallocated pids Li Chen
2026-07-16 14:31 ` [RFC PATCH 10/24] pidfs: publish future pidfd files Li Chen
2026-07-16 14:31 ` [RFC PATCH 11/24] pidfd: add spawn builder state tracking Li Chen
2026-07-16 14:31 ` [RFC PATCH 12/24] fork: let kernel callers create embryonic tasks Li Chen
2026-07-16 15:57   ` Andy Lutomirski
2026-08-19 10:19     ` Li Chen
2026-07-16 14:31 ` [RFC PATCH 13/24] fork: let new tasks start with task work Li Chen
2026-07-16 14:31 ` [RFC PATCH 14/24] pidfd: create and execute spawn builder tasks Li Chen
2026-07-16 14:31 ` [RFC PATCH 15/24] fork: keep embryonic tasks hidden until exec completes Li Chen
2026-07-16 14:31 ` [RFC PATCH 16/24] audit: add pidfd spawn child contexts Li Chen
2026-07-16 14:31 ` [RFC PATCH 17/24] pidfd: audit child spawn execution Li Chen
2026-07-16 14:31 ` [RFC PATCH 18/24] pidfd: make spawn builder execution signal-safe Li Chen
2026-07-16 14:31 ` [RFC PATCH 19/24] file: expose spawn file-action helpers Li Chen
2026-07-16 14:31 ` [RFC PATCH 20/24] pidfd: add initial spawn file actions Li Chen
2026-07-16 14:31 ` [RFC PATCH 21/24] pidfd: consume spawn builders on the first run attempt Li Chen
2026-07-16 14:31 ` [RFC PATCH 22/24] pidfd: expose spawn builder system calls Li Chen
2026-07-16 14:31 ` [RFC PATCH 23/24] selftests/pidfd: cover pidfd spawn builders Li Chen
2026-07-16 14:31 ` [RFC PATCH 24/24] Documentation: describe " Li Chen
2026-08-04 20:25 ` Justin Suess [this message]
2026-08-19  1:14   ` [RFC PATCH 00/24] pidfd: add a minimal process spawn builder Li Chen
2026-08-25 21:27     ` Mateusz Guzik
2026-09-06 10:50       ` Li Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=anJE8SfBLtkh6QSa@zenbox \
    --to=utilityemal77@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=audit@vger.kernel.org \
    --cc=brauner@kernel.org \
    --cc=corbet@lwn.net \
    --cc=eparis@redhat.com \
    --cc=gnoack@google.com \
    --cc=jack@suse.cz \
    --cc=josh@joshtriplett.org \
    --cc=kees@kernel.org \
    --cc=krisman@kernel.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mail@johnericson.me \
    --cc=me@linux.beauty \
    --cc=mic@digikod.net \
    --cc=mjguzik@gmail.com \
    --cc=oleg@redhat.com \
    --cc=paul@paul-moore.com \
    --cc=shuah@kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.