about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-09-08 04:06:34 +0000
committerLaurent Bercot <ska@appnovation.com>2023-09-08 04:06:34 +0000
commit15ebb5b8add8ee6a304981dd604fae78f491b34c (patch)
treeead3340839fdd15066ce95f51235e21740a07d8f /src
parent1cbe4b09e027e31d258c24feee0be46958888b93 (diff)
downloads6-15ebb5b8add8ee6a304981dd604fae78f491b34c.tar.gz
s6-15ebb5b8add8ee6a304981dd604fae78f491b34c.tar.xz
s6-15ebb5b8add8ee6a304981dd604fae78f491b34c.zip
Add ucspiserver.h, support posix_spawn() in s6-ipcserverd
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src')
-rw-r--r--src/conn-tools/deps-exe/s6-ipcserverd1
-rw-r--r--src/conn-tools/s6-ipcserverd.c74
-rw-r--r--src/include/s6/s6.h1
-rw-r--r--src/include/s6/ucspiserver.h10
-rw-r--r--src/libs6/deps-lib/s61
-rw-r--r--src/libs6/s6_ucspiserver_spawn.c116
6 files changed, 162 insertions, 41 deletions
diff --git a/src/conn-tools/deps-exe/s6-ipcserverd b/src/conn-tools/deps-exe/s6-ipcserverd
index 19869b2..bfcb622 100644
--- a/src/conn-tools/deps-exe/s6-ipcserverd
+++ b/src/conn-tools/deps-exe/s6-ipcserverd
@@ -1,2 +1,3 @@
+${LIBS6}
 -lskarnet
 ${SOCKET_LIB}
diff --git a/src/conn-tools/s6-ipcserverd.c b/src/conn-tools/s6-ipcserverd.c
index 3de8fae..35afdc5 100644
--- a/src/conn-tools/s6-ipcserverd.c
+++ b/src/conn-tools/s6-ipcserverd.c
@@ -22,9 +22,11 @@
 #include <skalibs/socket.h>
 #include <skalibs/exec.h>
 
+#include <s6/ucspiserver.h>
+
 #define USAGE "s6-ipcserverd [ -v verbosity ] [ -1 ] [ -P | -p ] [ -c maxconn ] [ -C localmaxconn ] prog..."
 
-#define ABSOLUTE_MAXCONN 1000
+#define ABSOLUTE_MAXCONN 16384
 
 static unsigned int maxconn = 40 ;
 static unsigned int localmaxconn = 40 ;
@@ -228,43 +230,16 @@ static inline void handle_signals (void)
 
  /* New connection handling */
 
-static void run_child (int, uid_t, gid_t, unsigned int, char const *, char const *const *) gccattr_noreturn ;
-static void run_child (int s, uid_t uid, gid_t gid, unsigned int num, char const *remotepath, char const *const *argv)
-{
-  size_t rplen = strlen(remotepath) + 1 ;
-  unsigned int n = 0 ;
-  char fmt[65 + UID_FMT + GID_FMT + UINT_FMT + rplen] ;
-  PROG = "s6-ipcserver (child)" ;
-  if ((fd_move(1, s) < 0) || (fd_copy(0, 1) < 0))
-    strerr_diefu1sys(111, "move fds") ;
-  memcpy(fmt+n, "PROTO=IPC\0IPCREMOTEEUID", 23) ; n += 23 ;
-  if (flaglookup)
-  {
-    fmt[n++] = '=' ;
-    n += uid_fmt(fmt+n, uid) ;
-  }
-  fmt[n++] = 0 ;
-  memcpy(fmt+n, "IPCREMOTEEGID", 13) ; n += 13 ;
-  if (flaglookup)
-  {
-    fmt[n++] = '=' ;
-    n += gid_fmt(fmt+n, gid) ;
-  }
-  fmt[n++] = 0 ;
-  memcpy(fmt+n, "IPCCONNNUM=", 11) ; n += 11 ;
-  if (flaglookup) n += uint_fmt(fmt+n, num) ;
-  fmt[n++] = 0 ;
-  memcpy(fmt+n, "IPCREMOTEPATH=", 14) ; n += 14 ;
-  memcpy(fmt+n, remotepath, rplen) ; n += rplen ;
-  xmexec_n(argv, fmt, n, 5) ;
-}
-
-static void new_connection (int s, char const *remotepath, char const *const *argv)
+static void new_connection (int s, char const *remotepath, char const *const *argv, char const *const *envp, size_t envlen)
 {
   uid_t uid = 0 ;
   gid_t gid = 0 ;
+  size_t m = 0 ;
+  size_t rplen = strlen(remotepath) + 1 ;
   pid_t pid ;
   unsigned int num, i ;
+  char fmt[65 + UID_FMT + GID_FMT + UINT_FMT + rplen] ;
+
   if (flaglookup && (getpeereid(s, &uid, &gid) < 0))
   {
     if (verbosity) strerr_warnwu1sys("getpeereid") ;
@@ -277,16 +252,32 @@ static void new_connection (int s, char const *remotepath, char const *const *ar
     log_deny(uid, gid, num) ;
     return ;
   }
-  pid = fork() ;
-  if (pid < 0)
+
+  memcpy(fmt + m, "PROTO=IPC\0IPCREMOTEEUID", 23) ; m += 23 ;
+  if (flaglookup)
   {
-    if (verbosity) strerr_warnwu1sys("fork") ;
-    return ;
+    fmt[m++] = '=' ;
+    m += uid_fmt(fmt + m, uid) ;
+  }
+  fmt[m++] = 0 ;
+  memcpy(fmt + m, "IPCREMOTEEGID", 13) ; m += 13 ;
+  if (flaglookup)
+  {
+    fmt[m++] = '=' ;
+    m += gid_fmt(fmt + m, gid) ;
   }
-  else if (!pid)
+  fmt[m++] = 0 ;
+  memcpy(fmt + m, "IPCCONNNUM=", 11) ; m += 11 ;
+  if (flaglookup) m += uint_fmt(fmt + m, num) ;
+  fmt[m++] = 0 ;
+  memcpy(fmt + m, "IPCREMOTEPATH=", 14) ; m += 14 ;
+  memcpy(fmt + m, remotepath, rplen) ; m += rplen ;
+
+  pid = s6_ucspiserver_spawn(s, argv, envp, envlen, fmt, m, 5) ;
+  if (!pid)
   {
-    selfpipe_finish() ;
-    run_child(s, uid, gid, num+1, remotepath, argv) ;
+    if (verbosity) strerr_warnwu1sys("fork") ;
+    return ;
   }
 
   if (i < uidlen) uidnum[i].right = num + 1 ;
@@ -376,6 +367,7 @@ int main (int argc, char const *const *argv)
   {
     piduid_t inyostack0[maxconn] ;
     uidnum_t inyostack1[flaglookup ? maxconn : 1] ;
+    size_t envlen = env_len((char const *const *)environ) ;
     piduid = inyostack0 ;
     uidnum = inyostack1 ;
 
@@ -400,7 +392,7 @@ int main (int argc, char const *const *argv)
           }
           else
           {
-            new_connection(sock, remotepath, argv) ;
+            new_connection(sock, remotepath, argv, (char const *const *)environ, envlen) ;
             fd_close(sock) ;
           }
         }
diff --git a/src/include/s6/s6.h b/src/include/s6/s6.h
index ef521bb..31b8e00 100644
--- a/src/include/s6/s6.h
+++ b/src/include/s6/s6.h
@@ -10,5 +10,6 @@
 #include <s6/accessrules.h>
 #include <s6/lock.h>
 #include <s6/auto.h>
+#include <s6/ucspiserver.h>
 
 #endif
diff --git a/src/include/s6/ucspiserver.h b/src/include/s6/ucspiserver.h
new file mode 100644
index 0000000..7ae03c2
--- /dev/null
+++ b/src/include/s6/ucspiserver.h
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#ifndef S6_SERVER_H
+#define S6_SERVER_H
+
+#include <sys/types.h>
+
+extern pid_t s6_ucspiserver_spawn (int, char const *const *, char const *const *, size_t, char const *, size_t, size_t) ;
+
+#endif
diff --git a/src/libs6/deps-lib/s6 b/src/libs6/deps-lib/s6
index 9924d83..13b9a83 100644
--- a/src/libs6/deps-lib/s6
+++ b/src/libs6/deps-lib/s6
@@ -70,4 +70,5 @@ s6_supervise_link.o
 s6_supervise_link_names.o
 s6_supervise_unlink.o
 s6_supervise_unlink_names.o
+s6_ucspiserver_spawn.o
 -lskarnet
diff --git a/src/libs6/s6_ucspiserver_spawn.c b/src/libs6/s6_ucspiserver_spawn.c
new file mode 100644
index 0000000..982d754
--- /dev/null
+++ b/src/libs6/s6_ucspiserver_spawn.c
@@ -0,0 +1,116 @@
+/* ISC license. */
+
+#include <skalibs/sysdeps.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <skalibs/uint16.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/djbunix.h>
+
+#include <s6/ucspiserver.h>
+
+#ifdef SKALIBS_HASPOSIXSPAWN
+
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <spawn.h>
+
+#include <skalibs/config.h>
+#include <skalibs/env.h>
+
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+extern pid_t child_spawn_workaround (pid_t, int const *) ;  /* XXX: non-public skalibs function */
+#endif
+
+pid_t s6_ucspiserver_spawn (int fd, char const *const *argv, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen, size_t modifn)
+{
+  pid_t pid ;
+  posix_spawn_file_actions_t actions ;
+  posix_spawnattr_t attr ;
+  sigset_t set ;
+  int e ;
+  int nopath = !getenv("PATH") ;
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+  int p[2] ;
+#endif
+  char const *newenvp[envlen + modifn + 1] ;
+
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+  if (pipecoe(p) == -1) return 0 ;
+#endif
+  e = posix_spawnattr_init(&attr) ;
+  if (e) goto err ;
+  sigemptyset(&set) ;
+  e = posix_spawnattr_setsigmask(&attr, &set) ;
+  if (e) goto errattr ;
+  e = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK) ;
+  if (e) goto errattr ;
+  e = posix_spawn_file_actions_init(&actions) ;
+  if (e) goto errattr ;
+  e = posix_spawn_file_actions_adddup2(&actions, fd, 0) ;
+  if (e) goto erractions ;
+  e = posix_spawn_file_actions_adddup2(&actions, fd, 1) ;
+  if (e) goto erractions ;
+  if (fd > 1)
+  {
+    e = posix_spawn_file_actions_addclose(&actions, fd) ;
+    if (e) goto erractions ;
+  }
+
+  env_mergen(newenvp, envlen + modifn + 1, envp, envlen, modifs, modiflen, modifn) ;
+  if (nopath && (setenv("PATH", SKALIBS_DEFAULTPATH, 0) < 0)) { e = errno ; goto erractions ; }
+  e = posix_spawnp(&pid, argv[0], &actions, &attr, (char *const *)argv, (char *const *)newenvp) ;
+  if (nopath) unsetenv("PATH") ;
+  if (e) goto erractions ;
+
+  posix_spawn_file_actions_destroy(&actions) ;
+  posix_spawnattr_destroy(&attr) ;
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+  return child_spawn_workaround(pid, p) ;
+#else
+  return pid ;
+#endif
+
+ erractions:
+  posix_spawn_file_actions_destroy(&actions) ;
+ errattr:
+  posix_spawnattr_destroy(&attr) ;
+ err:
+#ifdef SKALIBS_HASPOSIXSPAWNEARLYRETURN
+  fd_close(p[1]) ;
+  fd_close(p[0]) ;
+#endif
+  errno = e ;
+  return 0 ;
+}
+
+#else
+
+#include <skalibs/strerr.h>
+#include <skalibs/selfpipe.h>
+#include <skalibs/exec.h>
+
+pid_t s6_ucspiserver_spawn (int fd, char const *const *argv, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen, size_t modifn)
+{
+  pid_t pid = fork() ;
+  if (pid == -1) return 0 ;
+  if (!pid)
+  {
+    size_t proglen = strlen(PROG) ;
+    char newprog[proglen + 9] ;
+    memcpy(newprog, PROG, proglen) ;
+    memcpy(newprog, " (child)", 9) ;
+    PROG = newprog ;
+    if ((fd_move(1, fd) == -1) || (fd_copy(0, 1) == -1))
+      strerr_diefu1sys(111, "move fds") ;
+    selfpipe_finish() ;
+    xmexec_fn(argv, envp, envlen, modifs, modiflen, modifn) ;
+  }
+  return pid ;
+}
+
+#endif