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:
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