skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

commit f020ee0ec716aca176cbde6686e9a51d93bb65ab
parent 4dcf9fa0521a1c4243c28fb2f657d8029317e55e
Author: ccx <ccx@te2000.cz>
Date:   Fri, 31 May 2024 19:56:36 +0000

Barebones hardcoded implementation of CLONE_NEWPID

Diffstat:
Msrc/include/skalibs/cspawn.h | 1+
Msrc/libenvexec/cspawn.c | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/src/include/skalibs/cspawn.h b/src/include/skalibs/cspawn.h @@ -9,6 +9,7 @@ #define CSPAWN_FLAGS_SELFPIPE_FINISH 0x0001U #define CSPAWN_FLAGS_SIGBLOCKNONE 0x0002U #define CSPAWN_FLAGS_SETSID 0x0004U +#define CSPAWN_FLAGS_LINUX_NEWPID 0x0100U enum cspawn_fileaction_type_e { diff --git a/src/libenvexec/cspawn.c b/src/libenvexec/cspawn.c @@ -9,6 +9,11 @@ #include <errno.h> #include <unistd.h> +/* for CSPAWN_FLAGS_LINUX_NEWPID (using clone3 syscall) */ +#include <syscall.h> /* For calling clone3 syscall (currently not in libc) */ +#include <linux/types.h> /* For vendored definition of struct clone_args */ +#include <sched.h> /* Definition of CLONE_* constants */ + #include <skalibs/allreadwrite.h> #include <skalibs/sig.h> #include <skalibs/djbunix.h> @@ -94,6 +99,67 @@ static inline pid_t cspawn_fork (char const *prog, char const *const *argv, char return pid ; } +static inline pid_t cspawn_newpid_fork(void) +{ + struct clone_args { + __aligned_u64 flags; + __aligned_u64 pidfd; + __aligned_u64 child_tid; + __aligned_u64 parent_tid; + __aligned_u64 exit_signal; + __aligned_u64 stack; + __aligned_u64 stack_size; + __aligned_u64 tls; + __aligned_u64 set_tid; + __aligned_u64 set_tid_size; + __aligned_u64 cgroup; + } args = { + .flags = CLONE_NEWPID, + .exit_signal = SIGCHLD, + }; + + return syscall(__NR_clone3, &args, sizeof(args)); +} + +static inline pid_t cspawn_newpid (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) +{ + pid_t pid ; + int p[2] ; + char c ; + + if (pipecoe(p) == -1) return 0 ; + pid = cspawn_newpid_fork() ; + if (pid == -1) + { + fd_close(p[1]) ; + fd_close(p[0]) ; + return 0 ; + } + if (!pid) + { + cspawn_child_exec(prog, argv, envp, flags, fa, n) ; + c = errno ; + fd_write(p[1], &c, 1) ; + _exit(127) ; + } + + fd_close(p[1]) ; + p[1] = fd_read(p[0], &c, 1) ; + if (p[1] < 0) + { + fd_close(p[0]) ; + return 0 ; + } + fd_close(p[0]) ; + if (p[1]) + { + wait_pid(pid, &p[0]) ; + errno = (unsigned char)c ; + return 0 ; + } + return pid ; +} + /* guess who has a buggy posix_spawn() *and* doesn't have waitid() to work around it? if you guessed OpenBSD, you're right! @@ -271,6 +337,9 @@ pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp pid_t cspawn (char const *prog, char const *const *argv, char const *const *envp, uint16_t flags, cspawn_fileaction const *fa, size_t n) { + if (flags & CSPAWN_FLAGS_LINUX_NEWPID) + return cspawn_newpid(prog, argv, envp, flags, fa, n) ; + #if !defined(SKALIBS_HASPOSIXSPAWNSETSID) && !defined(SKALIBS_HASPOSIXSPAWNSETSIDNP) if (flags & CSPAWN_FLAGS_SETSID) goto dofork ; #endif