From 15ebb5b8add8ee6a304981dd604fae78f491b34c Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Fri, 8 Sep 2023 04:06:34 +0000 Subject: Add ucspiserver.h, support posix_spawn() in s6-ipcserverd Signed-off-by: Laurent Bercot --- src/conn-tools/deps-exe/s6-ipcserverd | 1 + src/conn-tools/s6-ipcserverd.c | 74 ++++++++++------------ src/include/s6/s6.h | 1 + src/include/s6/ucspiserver.h | 10 +++ src/libs6/deps-lib/s6 | 1 + src/libs6/s6_ucspiserver_spawn.c | 116 ++++++++++++++++++++++++++++++++++ 6 files changed, 162 insertions(+), 41 deletions(-) create mode 100644 src/include/s6/ucspiserver.h create mode 100644 src/libs6/s6_ucspiserver_spawn.c (limited to 'src') 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 #include +#include + #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 #include #include +#include #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 + +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 + +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef SKALIBS_HASPOSIXSPAWN + +#include +#include +#include +#include + +#include +#include + +#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 +#include +#include + +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 -- cgit 1.4.1