[PATCH v2] s6-supervise: Optionally run child in a new pid namespace

From: Jesse Young <jlyo_at_jlyo.org>
Date: Mon, 14 Jun 2021 14:53:44 -0500

Signed-off-by: Jesse Young <jlyo_at_jlyo.org>
---
 Hello,
 This is an update on my previous patch [1], reworking it to make the
 delta a lot nicer. fork_newpid() uses sigjmp()/longjmp() to wrap the
 clone() call, giving it the same double return semantics as fork().
 I'm not asking for inclusion of this into s6 as it's Linux specific. I
 find it useful in my environment especially when doing a s6-svc -k,
 which will reliably kill the process under supervision and all of its
 descendants. If you just need pid isolation, Linux has the hidepid=2
 mount option for procfs, isolating processes to the same UIDs.
 Another way to kill an entire process subtree in Linux is to run the
 tree in a cgroup freezer in order to send a SIGKILL+SIGCONT to all
 processes in the cgroup while frozen. Freezing the processes prevents
 the processes themselves from fork()ing, causing a race with the killer.
 For lack of a good header file in s6 to put the fork_newpid(), I'm only
 defining it as a symbol. The pozixplz.h header in skalibs could be
 a candidate, but I haven't had a use for fork_newpid() outside of
 s6-supervise.
 As in the v1 patch, touching a file called "clone-newpid" in the
 service directory will cause s6-supervise to spawn the ./run script
 in a new Linux pid namespace.
 It's slightly related to my previous gccattr_returns_twice patch
 for skalibs, but that's a nice-to-have. I can update this patch when
 gccattr_returns_twice is released.
 Jesse
 [1] https://www.mail-archive.com/skaware_at_list.skarnet.org/msg01006.html
 package/deps.mak               |  4 ++++
 src/libs6/deps-lib/s6          |  1 +
 src/libs6/fork_newpid.c        | 24 ++++++++++++++++++++++++
 src/supervision/s6-supervise.c |  4 +++-
 4 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 src/libs6/fork_newpid.c
diff --git a/package/deps.mak b/package/deps.mak
index 3c051aa..a3520a9 100644
--- a/package/deps.mak
+++ b/package/deps.mak
_at__at_ -40,6 +40,7 _at__at_ src/fdholder/s6-fdholder-setdump.o src/fdholder/s6-fdholder-setdump.lo: src/fdho
 src/fdholder/s6-fdholder-store.o src/fdholder/s6-fdholder-store.lo: src/fdholder/s6-fdholder-store.c src/include/s6/s6-fdholder.h
 src/fdholder/s6-fdholder-transferdump.o src/fdholder/s6-fdholder-transferdump.lo: src/fdholder/s6-fdholder-transferdump.c src/include/s6/s6-fdholder.h
 src/fdholder/s6-fdholderd.o src/fdholder/s6-fdholderd.lo: src/fdholder/s6-fdholderd.c src/include/s6/accessrules.h src/include/s6/s6-fdholder.h
+src/libs6/fork_newpid.o src/libs6/fork_newpid.lo: src/libs6/fork_newpid.c
 src/libs6/ftrig1_free.o src/libs6/ftrig1_free.lo: src/libs6/ftrig1_free.c src/libs6/ftrig1.h
 src/libs6/ftrig1_make.o src/libs6/ftrig1_make.lo: src/libs6/ftrig1_make.c src/libs6/ftrig1.h
 src/libs6/ftrigr1_zero.o src/libs6/ftrigr1_zero.lo: src/libs6/ftrigr1_zero.c src/include/s6/ftrigr.h
_at__at_ -203,11 +204,14 _at__at_ s6-fdholder-transferdump: src/fdholder/s6-fdholder-transferdump.o ${LIBS6}
 s6-fdholderd: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
 s6-fdholderd: src/fdholder/s6-fdholderd.o ${LIBS6}
 ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
+libs6.a.xyzzy: src/libs6/fork_newpid.o
 libs6.a.xyzzy: src/libs6/ftrigr1_zero.o src/libs6/ftrigr_check.o src/libs6/ftrigr_checksa.o src/libs6/ftrigr_ack.o src/libs6/ftrigr_end.o src/libs6/ftrigr_start.o src/libs6/ftrigr_startf.o src/libs6/ftrigr_subscribe.o src/libs6/ftrigr_unsubscribe.o src/libs6/ftrigr_update.o src/libs6/ftrigr_updateb.o src/libs6/ftrigr_wait_and.o src/libs6/ftrigr_wait_or.o src/libs6/ftrigr_zero.o src/libs6/ftrigw_clean.o src/libs6/ftrigw_fifodir_make.o src/libs6/ftrigw_notify.o src/libs6/ftrigw_notifyb.o src/libs6/ftrigw_notifyb_nosig.o src/libs6/s6_accessrules_backend_cdb.o src/libs6/s6_accessrules_backend_fs.o src/libs6/s6_accessrules_keycheck_ip4.o src/libs6/s6_accessrules_keycheck_ip6.o src/libs6/s6_accessrules_keycheck_reversedns.o src/libs6/s6_accessrules_keycheck_uidgid.o src/libs6/s6_accessrules_params_free.o src/libs6/s6_accessrules_uidgid_cdb.o src/libs6/s6_accessrules_uidgid_fs.o src/libs6/s6_compat_el_semicolon.o src/libs6/s6_dtally_pack.o src/libs6/s6_dtally_unpack.o src/libs6/s6_dtally_read.o src/libs6/s6_dtally_write.o src/libs6/s6_svc_ok.o src/libs6/s6_svc_write.o src/libs6/s6_svc_writectl.o src/libs6/s6_svstatus_pack.o src/libs6/s6_svstatus_read.o src/libs6/s6_svstatus_unpack.o src/libs6/s6_svstatus_write.o src/libs6/s6lock_acquire.o src/libs6/s6lock_check.o src/libs6/s6lock_end.o src/libs6/s6lock_release.o src/libs6/s6lock_start.o src/libs6/s6lock_startf.o src/libs6/s6lock_update.o src/libs6/s6lock_wait_and.o src/libs6/s6lock_wait_or.o src/libs6/s6lock_zero.o src/libs6/s6_fdholder_delete.o src/libs6/s6_fdholder_delete_async.o src/libs6/s6_fdholder_end.o src/libs6/s6_fdholder_getdump.o src/libs6/s6_fdholder_list.o src/libs6/s6_fdholder_list_async.o src/libs6/s6_fdholder_list_cb.o src/libs6/s6_fdholder_retrieve.o src/libs6/s6_fdholder_retrieve_async.o src/libs6/s6_fdholder_retrieve_cb.o src/libs6/s6_fdholder_setdump.o src/libs6/s6_fdholder_start.o src/libs6/s6_fdholder_store.o src/libs6/s6_fdholder_store_async.o src/libs6/s6_supervise_link.o src/libs6/s6_supervise_unlink.o
 else
+libs6.a.xyzzy: src/libs6/fork_newpid.lo
 libs6.a.xyzzy: src/libs6/ftrigr1_zero.lo src/libs6/ftrigr_check.lo src/libs6/ftrigr_checksa.lo src/libs6/ftrigr_ack.lo src/libs6/ftrigr_end.lo src/libs6/ftrigr_start.lo src/libs6/ftrigr_startf.lo src/libs6/ftrigr_subscribe.lo src/libs6/ftrigr_unsubscribe.lo src/libs6/ftrigr_update.lo src/libs6/ftrigr_updateb.lo src/libs6/ftrigr_wait_and.lo src/libs6/ftrigr_wait_or.lo src/libs6/ftrigr_zero.lo src/libs6/ftrigw_clean.lo src/libs6/ftrigw_fifodir_make.lo src/libs6/ftrigw_notify.lo src/libs6/ftrigw_notifyb.lo src/libs6/ftrigw_notifyb_nosig.lo src/libs6/s6_accessrules_backend_cdb.lo src/libs6/s6_accessrules_backend_fs.lo src/libs6/s6_accessrules_keycheck_ip4.lo src/libs6/s6_accessrules_keycheck_ip6.lo src/libs6/s6_accessrules_keycheck_reversedns.lo src/libs6/s6_accessrules_keycheck_uidgid.lo src/libs6/s6_accessrules_params_free.lo src/libs6/s6_accessrules_uidgid_cdb.lo src/libs6/s6_accessrules_uidgid_fs.lo src/libs6/s6_compat_el_semicolon.lo src/libs6/s6_dtally_pack.lo src/libs6/s6_dtally_unpack.lo src/libs6/s6_dtally_read.lo src/libs6/s6_dtally_write.lo src/libs6/s6_svc_ok.lo src/libs6/s6_svc_write.lo src/libs6/s6_svc_writectl.lo src/libs6/s6_svstatus_pack.lo src/libs6/s6_svstatus_read.lo src/libs6/s6_svstatus_unpack.lo src/libs6/s6_svstatus_write.lo src/libs6/s6lock_acquire.lo src/libs6/s6lock_check.lo src/libs6/s6lock_end.lo src/libs6/s6lock_release.lo src/libs6/s6lock_start.lo src/libs6/s6lock_startf.lo src/libs6/s6lock_update.lo src/libs6/s6lock_wait_and.lo src/libs6/s6lock_wait_or.lo src/libs6/s6lock_zero.lo src/libs6/s6_fdholder_delete.lo src/libs6/s6_fdholder_delete_async.lo src/libs6/s6_fdholder_end.lo src/libs6/s6_fdholder_getdump.lo src/libs6/s6_fdholder_list.lo src/libs6/s6_fdholder_list_async.lo src/libs6/s6_fdholder_list_cb.lo src/libs6/s6_fdholder_retrieve.lo src/libs6/s6_fdholder_retrieve_async.lo src/libs6/s6_fdholder_retrieve_cb.lo src/libs6/s6_fdholder_setdump.lo src/libs6/s6_fdholder_start.lo src/libs6/s6_fdholder_store.lo src/libs6/s6_fdholder_store_async.lo src/libs6/s6_supervise_link.lo src/libs6/s6_supervise_unlink.lo
 endif
 libs6.so.xyzzy: EXTRA_LIBS := -lskarnet
+libs6.so.xyzzy: src/libs6/fork_newpid.lo
 libs6.so.xyzzy: src/libs6/ftrigr1_zero.lo src/libs6/ftrigr_check.lo src/libs6/ftrigr_checksa.lo src/libs6/ftrigr_ack.lo src/libs6/ftrigr_end.lo src/libs6/ftrigr_start.lo src/libs6/ftrigr_startf.lo src/libs6/ftrigr_subscribe.lo src/libs6/ftrigr_unsubscribe.lo src/libs6/ftrigr_update.lo src/libs6/ftrigr_updateb.lo src/libs6/ftrigr_wait_and.lo src/libs6/ftrigr_wait_or.lo src/libs6/ftrigr_zero.lo src/libs6/ftrigw_clean.lo src/libs6/ftrigw_fifodir_make.lo src/libs6/ftrigw_notify.lo src/libs6/ftrigw_notifyb.lo src/libs6/ftrigw_notifyb_nosig.lo src/libs6/s6_accessrules_backend_cdb.lo src/libs6/s6_accessrules_backend_fs.lo src/libs6/s6_accessrules_keycheck_ip4.lo src/libs6/s6_accessrules_keycheck_ip6.lo src/libs6/s6_accessrules_keycheck_reversedns.lo src/libs6/s6_accessrules_keycheck_uidgid.lo src/libs6/s6_accessrules_params_free.lo src/libs6/s6_accessrules_uidgid_cdb.lo src/libs6/s6_accessrules_uidgid_fs.lo src/libs6/s6_compat_el_semicolon.lo src/libs6/s6_dtally_pack.lo src/libs6/s6_dtally_unpack.lo src/libs6/s6_dtally_read.lo src/libs6/s6_dtally_write.lo src/libs6/s6_svc_ok.lo src/libs6/s6_svc_write.lo src/libs6/s6_svc_writectl.lo src/libs6/s6_svstatus_pack.lo src/libs6/s6_svstatus_read.lo src/libs6/s6_svstatus_unpack.lo src/libs6/s6_svstatus_write.lo src/libs6/s6lock_acquire.lo src/libs6/s6lock_check.lo src/libs6/s6lock_end.lo src/libs6/s6lock_release.lo src/libs6/s6lock_start.lo src/libs6/s6lock_startf.lo src/libs6/s6lock_update.lo src/libs6/s6lock_wait_and.lo src/libs6/s6lock_wait_or.lo src/libs6/s6lock_zero.lo src/libs6/s6_fdholder_delete.lo src/libs6/s6_fdholder_delete_async.lo src/libs6/s6_fdholder_end.lo src/libs6/s6_fdholder_getdump.lo src/libs6/s6_fdholder_list.lo src/libs6/s6_fdholder_list_async.lo src/libs6/s6_fdholder_list_cb.lo src/libs6/s6_fdholder_retrieve.lo src/libs6/s6_fdholder_retrieve_async.lo src/libs6/s6_fdholder_retrieve_cb.lo src/libs6/s6_fdholder_setdump.lo src/libs6/s6_fdholder_start.lo src/libs6/s6_fdholder_store.lo src/libs6/s6_fdholder_store_async.lo src/libs6/s6_supervise_link.lo src/libs6/s6_supervise_unlink.lo
 ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
 libs6lockd.a.xyzzy: src/libs6/s6lockd_openandlock.o
diff --git a/src/libs6/deps-lib/s6 b/src/libs6/deps-lib/s6
index 45e6c33..85c70b6 100644
--- a/src/libs6/deps-lib/s6
+++ b/src/libs6/deps-lib/s6
_at__at_ -1,3 +1,4 _at__at_
+fork_newpid.o
 ftrigr1_zero.o
 ftrigr_check.o
 ftrigr_checksa.o
diff --git a/src/libs6/fork_newpid.c b/src/libs6/fork_newpid.c
new file mode 100644
index 0000000..457eca1
--- /dev/null
+++ b/src/libs6/fork_newpid.c
_at__at_ -0,0 +1,24 _at__at_
+#define _GNU_SOURCE
+
+#include <setjmp.h>
+#include <sched.h>
+#include <sys/wait.h>
+
+static int child(void *arg)
+{
+  sigjmp_buf *env = (jmp_buf *) arg ;
+  siglongjmp(*env, 1) ;
+}
+
+pid_t fork_newpid(void)
+{
+  sigjmp_buf env ;
+  if (!sigsetjmp(env, 0))
+  {
+    pid_t ppid, cpid ;
+    int flags = CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_NEWPID | SIGCHLD ;
+    unsigned long stack[1][128] ;
+    return clone(&child, &stack[1], flags, &env, &ppid, NULL, &cpid) ;
+  }
+  return 0 ;
+}
diff --git a/src/supervision/s6-supervise.c b/src/supervision/s6-supervise.c
index bda8e52..bc55b81 100644
--- a/src/supervision/s6-supervise.c
+++ b/src/supervision/s6-supervise.c
_at__at_ -37,6 +37,8 _at__at_
 # define S6_PATH_MAX 4096
 #endif
 
+extern pid_t fork_newpid(void) ;
+
 typedef enum trans_e trans_t, *trans_t_ref ;
 enum trans_e
 {
_at__at_ -253,7 +255,7 _at__at_ static void trystart (void)
     fd_close(p[1]) ; fd_close(p[0]) ;
     return ;
   }
-  pid = fork() ;
+  pid = access("clone-newpid", R_OK) ? fork() : fork_newpid() ;
   if (pid < 0)
   {
     settimeout(60) ;
-- 
2.32.0
Received on Mon Jun 14 2021 - 21:53:44 CEST

This archive was generated by hypermail 2.4.0 : Mon Jun 14 2021 - 21:54:16 CEST