diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2020-12-04 07:25:12 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2020-12-04 07:25:12 +0000 |
commit | 5a318ce649a7a5f754892518a4452a519b41dac8 (patch) | |
tree | ad4a8447fd8dc6cce82c1586bbb62566ea8f7e93 /src/supervision | |
parent | ffb0a8fd2045bb8f7f097905cb9d0814803c6060 (diff) | |
download | s6-5a318ce649a7a5f754892518a4452a519b41dac8.tar.gz s6-5a318ce649a7a5f754892518a4452a519b41dac8.tar.xz s6-5a318ce649a7a5f754892518a4452a519b41dac8.zip |
Big signal/command semantics change to svscan/supervise; add s6-svperms.
Diffstat (limited to 'src/supervision')
-rw-r--r-- | src/supervision/deps-exe/s6-supervise | 2 | ||||
-rw-r--r-- | src/supervision/deps-exe/s6-svperms | 1 | ||||
-rw-r--r-- | src/supervision/s6-supervise.c | 108 | ||||
-rw-r--r-- | src/supervision/s6-svc.c | 3 | ||||
-rw-r--r-- | src/supervision/s6-svperms.c | 272 | ||||
-rw-r--r-- | src/supervision/s6-svscan.c | 2 |
6 files changed, 320 insertions, 68 deletions
diff --git a/src/supervision/deps-exe/s6-supervise b/src/supervision/deps-exe/s6-supervise index b1e57e4..34dc00e 100644 --- a/src/supervision/deps-exe/s6-supervise +++ b/src/supervision/deps-exe/s6-supervise @@ -1,3 +1,3 @@ -${LIBS6} +libs6.a.xyzzy -lskarnet ${SYSCLOCK_LIB} diff --git a/src/supervision/deps-exe/s6-svperms b/src/supervision/deps-exe/s6-svperms new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/supervision/deps-exe/s6-svperms @@ -0,0 +1 @@ +-lskarnet diff --git a/src/supervision/s6-supervise.c b/src/supervision/s6-supervise.c index a8be37d..a175f0a 100644 --- a/src/supervision/s6-supervise.c +++ b/src/supervision/s6-supervise.c @@ -40,9 +40,9 @@ typedef enum trans_e trans_t, *trans_t_ref ; enum trans_e { - V_TIMEOUT, V_CHLD, V_TERM, V_HUP, V_QUIT, - V_a, V_b, V_q, V_h, V_k, V_t, V_i, V_1, V_2, V_f, V_F, V_p, V_c, V_y, V_r, - V_o, V_d, V_u, V_x, V_O, V_X + V_TIMEOUT, V_CHLD, V_TERM, V_HUP, V_QUIT, V_INT, + V_a, V_b, V_q, V_h, V_k, V_t, V_i, V_1, V_2, V_p, V_c, V_y, V_r, + V_o, V_d, V_u, V_x, V_O } ; typedef enum state_e state_t, *state_t_ref ; @@ -140,14 +140,22 @@ static void bail (void) cont = 0 ; } +static void sigint (void) +{ + pid_t pgid = getpgid(status.pid) ; + if (pgid == -1) strerr_warnwu1sys("getpgid") ; + else killpg(pgid, SIGINT) ; + bail() ; +} + static void closethem (void) { - close(0) ; - close(1) ; - close(2) ; - open_readb("/dev/null") ; - open_write("/dev/null") ; ndelay_off(1) ; - open_write("/dev/null") ; ndelay_off(2) ; + fd_close(0) ; + fd_close(1) ; + if (open_readb("/dev/null")) + strerr_warnwu2sys("open /dev/null for ", "reading") ; + else if (open_write("/dev/null") != 1 || ndelay_off(1) < 0) + strerr_warnwu2sys("open /dev/null for ", "writing") ; } static void killa (void) @@ -226,24 +234,6 @@ static void failcoe (int fd) errno = e ; } -static int maybesetsid (void) -{ - char buf[8] = "-------" ; - ssize_t r = openreadnclose("nosetsid", buf, 8) ; - if (r < 0) - { - if (errno != ENOENT) return 0 ; - setsid() ; - } - else - { - if (r == 8 && buf[7] == '\n') buf[--r] = 0 ; - if (r == 7 && !strncasecmp(buf, "setpgrp", 7)) - setpgid(0, 0) ; - } - return 1 ; -} - static void trystart (void) { int p[2] ; @@ -285,11 +275,7 @@ static void trystart (void) failcoe(p[1]) ; strerr_diefu1sys(127, "move notification descriptor") ; } - if (!maybesetsid()) - { - failcoe(p[1]) ; - strerr_diefu1sys(127, "access ./nosetsid") ; - } + setsid() ; execv("./run", (char *const *)cargv) ; failcoe(p[1]) ; strerr_dieexec(127, "run") ; @@ -407,7 +393,7 @@ static int uplastup_z (void) selfpipe_finish() ; fmt0[uint_fmt(fmt0, WIFSIGNALED(status.wstat) ? 256 : WEXITSTATUS(status.wstat))] = 0 ; fmt1[uint_fmt(fmt1, WTERMSIG(status.wstat))] = 0 ; - maybesetsid() ; + setsid() ; execv("./finish", cargv) ; _exit(127) ; } @@ -481,17 +467,12 @@ static void up_u (void) static void up_x (void) { state = LASTUP ; -} - -static void up_X (void) -{ closethem() ; - up_x() ; } static void up_term (void) { - up_x() ; + state = LASTUP ; up_d() ; } @@ -522,12 +503,7 @@ static void finish_u (void) static void finish_x (void) { state = LASTFINISH ; -} - -static void finish_X (void) -{ closethem() ; - finish_x() ; } static void lastfinish_z (void) @@ -536,23 +512,23 @@ static void lastfinish_z (void) bail() ; } -static action_t_ref const actions[5][26] = -{ - { &downtimeout, &nop, &bail, &bail, &bail, - &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, - &down_o, &down_d, &down_u, &bail, &down_O, &bail }, - { &uptimeout, &up_z, &up_term, &up_x, &up_X, - &killa, &killb, &killq, &killh, &killk, &killt, &killi, &kill1, &kill2, &nop, &nop, &killp, &killc, &killy, &killr, - &up_o, &up_d, &up_u, &up_x, &up_o, &up_X }, - { &finishtimeout, &finish_z, &finish_x, &finish_x, &finish_X, - &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, - &up_o, &down_d, &finish_u, &finish_x, &up_o, &finish_X }, - { &uptimeout, &lastup_z, &up_d, &nop, &closethem, - &killa, &killb, &killq, &killh, &killk, &killt, &killi, &kill1, &kill2, &nop, &nop, &killp, &killc, &killy, &killr, - &up_o, &up_d, &nop, &nop, &up_o, &closethem }, - { &finishtimeout, &lastfinish_z, &nop, &nop, &closethem, - &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, - &nop, &nop, &nop, &nop, &nop, &closethem } +static action_t_ref const actions[5][24] = +{ + { &downtimeout, &nop, &bail, &bail, &bail, &bail, + &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, + &down_o, &down_d, &down_u, &bail, &down_O }, + { &uptimeout, &up_z, &up_term, &up_x, &bail, &sigint, + &killa, &killb, &killq, &killh, &killk, &killt, &killi, &kill1, &kill2, &killp, &killc, &killy, &killr, + &up_o, &up_d, &up_u, &up_x, &up_o }, + { &finishtimeout, &finish_z, &finish_x, &finish_x, &bail, &sigint, + &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, + &up_o, &down_d, &finish_u, &finish_x, &up_o }, + { &uptimeout, &lastup_z, &up_d, &closethem, &bail, &sigint, + &killa, &killb, &killq, &killh, &killk, &killt, &killi, &kill1, &kill2, &killp, &killc, &killy, &killr, + &up_o, &up_d, &nop, &nop, &up_o }, + { &finishtimeout, &lastfinish_z, &nop, &closethem, &bail, &sigint, + &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, &nop, + &nop, &nop, &nop, &nop, &nop } } ; @@ -615,6 +591,9 @@ static inline void handle_signals (void) case SIGQUIT : (*actions[state][V_QUIT])() ; break ; + case SIGINT : + (*actions[state][V_INT])() ; + break ; default : strerr_dief1x(101, "internal error: inconsistent signal state. Please submit a bug-report.") ; } @@ -631,8 +610,8 @@ static inline void handle_control (int fd) else if (!r) break ; else { - size_t pos = byte_chr("abqhkti12fFpcyroduxOX", 21, c) ; - if (pos < 21) (*actions[state][V_a + pos])() ; + size_t pos = byte_chr("abqhkti12pcyroduxO", 18, c) ; + if (pos < 18) (*actions[state][V_a + pos])() ; } } } @@ -736,10 +715,11 @@ int main (int argc, char const *const *argv) { sigset_t set ; sigemptyset(&set) ; + sigaddset(&set, SIGCHLD) ; sigaddset(&set, SIGTERM) ; sigaddset(&set, SIGHUP) ; sigaddset(&set, SIGQUIT) ; - sigaddset(&set, SIGCHLD) ; + sigaddset(&set, SIGINT) ; if (selfpipe_trapset(&set) < 0) strerr_diefu1sys(111, "trap signals") ; } diff --git a/src/supervision/s6-svc.c b/src/supervision/s6-svc.c index 3e024d6..a189d24 100644 --- a/src/supervision/s6-svc.c +++ b/src/supervision/s6-svc.c @@ -28,7 +28,7 @@ int main (int argc, char const *const *argv) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "abqhkti12pcyroduxOXT:w:", &l) ; + int opt = subgetopt_r(argc, argv, "abqhkti12pcyroduxOT:w:", &l) ; if (opt == -1) break ; switch (opt) { @@ -50,7 +50,6 @@ int main (int argc, char const *const *argv) case 'u' : case 'x' : case 'O' : - case 'X' : { if (datalen >= DATASIZE) strerr_dief1x(100, "too many commands") ; data[datalen++] = opt ; diff --git a/src/supervision/s6-svperms.c b/src/supervision/s6-svperms.c new file mode 100644 index 0000000..178ea08 --- /dev/null +++ b/src/supervision/s6-svperms.c @@ -0,0 +1,272 @@ +/* ISC license. */ + +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#include <pwd.h> +#include <grp.h> + +#include <skalibs/types.h> +#include <skalibs/sgetopt.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> + +#include <s6/s6-supervise.h> + +#define USAGE "s6-svperms [ -v ] [ -u | -g group | -G group | -o | -O group ] [ -e | -E group ] servicedir..." +#define dieusage() strerr_dieusage(100, USAGE) + +static gid_t scangid (char const *s) +{ + if (s[0] == ':') + { + gid_t g ; + if (!gid0_scan(s+1, &g)) dieusage() ; + return g ; + } + else + { + struct group *gr ; + errno = 0 ; + gr = getgrnam(s) ; + if (!gr) + { + if (errno) strerr_diefu1sys(111, "getgrnam") ; + else strerr_diefu3x(100, "find entry for ", s, " in group database") ; + } + return gr->gr_gid ; + } +} + +static char *gidname (gid_t gid) +{ + struct group *gr ; + errno = 0 ; + gr = getgrgid(gid) ; + if (!gr) + { + static char fmt[GID_FMT] ; + fmt[gid_fmt(fmt, gid)] = 0 ; + if (errno) strerr_warnwu2sys("getgrgid ", fmt) ; + return fmt ; + } + return gr->gr_name ; +} + +static void out (char const *s) +{ + if (buffer_puts(buffer_1, s) < 0) + strerr_diefu1sys(111, "write to stdout") ; +} + +static inline int printsupervise (char const *dir) +{ + struct stat st ; + size_t len = strlen(dir) ; + char fn[len + sizeof(S6_SUPERVISE_CTLDIR) + 9] ; + memcpy(fn, dir, len) ; + memcpy(fn + len, "/" S6_SUPERVISE_CTLDIR, sizeof(S6_SUPERVISE_CTLDIR) + 1) ; + if (stat(fn, &st) < 0) + { + strerr_warnwu2sys("stat ", fn) ; + return 1 ; + } + if (!S_ISDIR(st.st_mode)) + { + strerr_warnw2x(fn, " is not a directory") ; + return 1 ; + } + if (st.st_mode & 05066 || (st.st_mode & 0700) != 0700 || ((st.st_mode & 0001) && !(st.st_mode & 0010))) + { + char fmt[UINT_OFMT] ; + fmt[uint_ofmt(fmt, st.st_mode & 07777)] = 0 ; + strerr_warnw3x(fn, " has incorrect permissions: ", fmt) ; + return 1 ; + } + out(dir) ; + out(" status: ") ; + if (st.st_mode & 0011) + { + if (st.st_mode & 0001) buffer_puts(buffer_1, "public") ; + else + { + out("group ") ; + out(gidname(st.st_gid)) ; + } + } + else out("owner") ; + out("\n") ; + memcpy(fn + len + sizeof(S6_SUPERVISE_CTLDIR), "/control", 9) ; + if (stat(fn, &st) < 0) + { + strerr_warnwu2sys("stat ", fn) ; + return 1 ; + } + if (!S_ISFIFO(st.st_mode)) + { + strerr_warnw2x(fn, " is not a named pipe") ; + return 1 ; + } + if (st.st_mode & 0157) + { + char fmt[UINT_OFMT] ; + fmt[uint_ofmt(fmt, st.st_mode & 07777)] = 0 ; + strerr_warnw3x(fn, " has incorrect permissions: ", fmt) ; + return 1 ; + } + out(dir) ; + out(" control: ") ; + if (st.st_mode & 0020) + { + out("group ") ; + out(gidname(st.st_gid)) ; + } + else out("owner") ; + out("\n") ; + return 0 ; +} + +static inline int printevent (char const *dir) +{ + struct stat st ; + size_t len = strlen(dir) ; + char fn[len + sizeof(S6_SUPERVISE_EVENTDIR) + 1] ; + memcpy(fn, dir, len) ; + memcpy(fn + len, "/" S6_SUPERVISE_EVENTDIR, sizeof(S6_SUPERVISE_EVENTDIR) + 1) ; + if (stat(fn, &st) < 0) + { + strerr_warnwu2sys("stat ", fn) ; + return 1 ; + } + if (!S_ISDIR(st.st_mode)) + { + strerr_warnw2x(fn, " is not a directory") ; + return 1 ; + } + if ((st.st_mode & 07777) != 01733 && (st.st_mode & 07777) != 03730) + { + char fmt[UINT_OFMT] ; + fmt[uint_ofmt(fmt, st.st_mode & 07777)] = 0 ; + strerr_warnw3x(fn, " has incorrect permissions: ", fmt) ; + return 1 ; + } + out(dir) ; + out(" events: ") ; + if ((st.st_mode & 07777) == 03730) + { + out("group ") ; + out(gidname(st.st_gid)) ; + } + else out("public") ; + out("\n") ; + return 0 ; +} + +static gid_t primarygid (char const *fn) +{ + struct passwd *pw ; + struct stat st ; + if (stat(fn, &st) < 0) strerr_diefu2sys(111, "stat ", fn) ; + errno = 0 ; + pw = getpwuid(st.st_uid) ; + if (!pw) + { + strerr_warnwu3sys("determine primary gid for the owner of ", fn, " (using root instead)") ; + return 0 ; + } + else return pw->pw_gid ; +} + +static inline void modsupervise (char const *dir, unsigned int what, gid_t gid) +{ + size_t len = strlen(dir) ; + gid_t cgid = 0 ; + mode_t mode = 0700 ; + char fn[len + sizeof(S6_SUPERVISE_CTLDIR) + 9] ; + memcpy(fn, dir, len) ; + memcpy(fn + len, "/" S6_SUPERVISE_CTLDIR, sizeof(S6_SUPERVISE_CTLDIR) + 1) ; + switch (what & 3) + { + case 0 : cgid = primarygid(fn) ; mode = 0700 ; break ; + case 1 : cgid = gid ; mode = 0710 ; break ; + case 2 : cgid = primarygid(fn) ; mode = 0711 ; break ; + } + if (chown(fn, -1, cgid) < 0) + strerr_diefu2sys(111, "chown ", fn) ; + if (chmod(fn, mode) < 0) + strerr_diefu2sys(111, "chmod ", fn) ; + memcpy(fn + len + sizeof(S6_SUPERVISE_CTLDIR), "/control", 9) ; + if (what & 4) mode = 0620 ; + else + { + gid = primarygid(fn) ; + mode = 0600 ; + } + if (chown(fn, -1, gid) < 0) + strerr_diefu2sys(111, "chown ", fn) ; + if (chmod(fn, mode) < 0) + strerr_diefu2sys(111, "chmod ", fn) ; +} + +static inline void modevent (char const *dir, gid_t gid) +{ + size_t len = strlen(dir) ; + mode_t mode ; + char fn[len + sizeof(S6_SUPERVISE_EVENTDIR) + 1] ; + memcpy(fn, dir, len) ; + memcpy(fn + len, "/" S6_SUPERVISE_EVENTDIR, sizeof(S6_SUPERVISE_EVENTDIR) + 1) ; + if (gid == (gid_t)-1) + { + gid = primarygid(fn) ; + mode = 01733 ; + } + else mode = 03730 ; + if (chown(fn, -1, gid) < 0) + strerr_diefu2sys(111, "chown ", fn) ; + if (chmod(fn, mode) < 0) + strerr_diefu2sys(111, "chmod ", fn) ; +} + +int main (int argc, char const *const *argv) +{ + int e = 0 ; + gid_t gid = -1 ; + gid_t eventgid = -1 ; + int rw = 0 ; + unsigned int what = 0 ; + PROG = "s6-svperms" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "vug:G:oO:eE:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'v' : rw |= 1 ; break ; + case 'u' : rw |= 2 ; what = 0 ; break ; + case 'g' : rw |= 2 ; what = 1 ; gid = scangid(l.arg) ; break ; + case 'G' : rw |= 2 ; what = 5 ; gid = scangid(l.arg) ; break ; + case 'o' : rw |= 2 ; what = 2 ; break ; + case 'O' : rw |= 2 ; what = 6 ; gid = scangid(l.arg) ; break ; + case 'e' : rw |= 4 ; eventgid = -1 ; break ; + case 'E' : rw |= 4 ; eventgid = scangid(l.arg) ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) dieusage() ; + + if (!rw) rw = 1 ; + for (; *argv ; argv++) + { + if (rw & 2) modsupervise(*argv, what, gid) ; + if (rw & 4) modevent(*argv, eventgid) ; + if (rw & 1) { e |= printsupervise(*argv) ; e |= printevent(*argv) ; } + } + if (rw & 1 && !buffer_flush(buffer_1)) + strerr_diefu1sys(111, "write to stdout") ; + return e ; +} diff --git a/src/supervision/s6-svscan.c b/src/supervision/s6-svscan.c index 0a3c286..1d17a3a 100644 --- a/src/supervision/s6-svscan.c +++ b/src/supervision/s6-svscan.c @@ -497,7 +497,7 @@ static inline int control_init (void) strerr_dief1x(100, S6_SVSCAN_CTLDIR " exists and is not a directory") ; } - fdlck = open(LCK, O_WRONLY | O_NONBLOCK | O_CREAT | O_CLOEXEC, 0644) ; + fdlck = open(LCK, O_WRONLY | O_NONBLOCK | O_CREAT | O_CLOEXEC, 0600) ; if (fdlck < 0) strerr_diefu1sys(111, "open " LCK) ; r = fd_lock(fdlck, 1, 1) ; if (r < 0) strerr_diefu1sys(111, "lock " LCK) ; |