summaryrefslogtreecommitdiff
path: root/src/supervision
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2020-12-04 07:25:12 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2020-12-04 07:25:12 +0000
commit5a318ce649a7a5f754892518a4452a519b41dac8 (patch)
treead4a8447fd8dc6cce82c1586bbb62566ea8f7e93 /src/supervision
parentffb0a8fd2045bb8f7f097905cb9d0814803c6060 (diff)
downloads6-5a318ce649a7a5f754892518a4452a519b41dac8.tar.xz
Big signal/command semantics change to svscan/supervise; add s6-svperms.
Diffstat (limited to 'src/supervision')
-rw-r--r--src/supervision/deps-exe/s6-supervise2
-rw-r--r--src/supervision/deps-exe/s6-svperms1
-rw-r--r--src/supervision/s6-supervise.c108
-rw-r--r--src/supervision/s6-svc.c3
-rw-r--r--src/supervision/s6-svperms.c272
-rw-r--r--src/supervision/s6-svscan.c2
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) ;