From f8faba0c8f35d881c14161c9c3f9aab334593cb4 Mon Sep 17 00:00:00 2001 From: Radon Rosborough Date: Fri, 13 Aug 2021 19:17:44 -0700 Subject: [PATCH] Report exit status from sentinel via FIFO --- system/res/sentinel.bash | 9 +++- system/src/riju-system-privileged.c | 68 +++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/system/res/sentinel.bash b/system/res/sentinel.bash index b92c9f1..ab9bcd0 100755 --- a/system/res/sentinel.bash +++ b/system/res/sentinel.bash @@ -30,8 +30,13 @@ while read -t2 -r cmdline; do args=("${cmd[@]:2}") input="/var/cache/riju/share/cmd-${uuid}-input" output="/var/cache/riju/share/cmd-${uuid}-output" - mkfifo "${input}" "${output}" - ${maybe_pty:-} runuser -u riju -- bash -c 'exec "$@"' sentinel "${args[@]}" < "${input}" &> "${output}" & + status="/var/cache/riju/share/cmd-${uuid}-status" + mkfifo "${input}" "${output}" "${status}" + ( + set +e + ${maybe_pty:-} runuser -u riju -- bash -c 'exec "$@"' sentinel "${args[@]}" < "${input}" &> "${output}" + echo "$?" > "${status}" + ) & fi ;; *) diff --git a/system/src/riju-system-privileged.c b/system/src/riju-system-privileged.c index 543ea46..55425f7 100644 --- a/system/src/riju-system-privileged.c +++ b/system/src/riju-system-privileged.c @@ -122,6 +122,16 @@ void wait_alarm(int signum) die(timeout_msg); } +void wait_alarm_group(int signum) +{ + (void)signum; + if (signal(SIGTERM, SIG_IGN) == SIG_ERR) + die("signal failed"); + if (kill(0, SIGTERM) < 0) + die("kill failed"); + die(timeout_msg); +} + void session(char *uuid, char *lang, char *imageHash) { if (setvbuf(stdout, NULL, _IONBF, 0) != 0) @@ -278,7 +288,8 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) { if (setvbuf(stdout, NULL, _IONBF, 0) != 0) die("setvbuf failed"); - char *share, *ctlFIFO, *inputFIFO, *outputFIFO, *ctlCmd, *dataFIFO; + char *share, *ctlFIFO, *inputFIFO, *outputFIFO, *statusFIFO, *ctlCmd, + *dataFIFO; if (asprintf(&share, "/var/cache/riju/shares/%s", uuid) < 0) die("asprintf failed"); if (asprintf(&ctlFIFO, "%s/control", share) < 0) @@ -288,6 +299,8 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) die("asprintf failed"); if (asprintf(&outputFIFO, "%s/cmd-%s-output", share, procUUID) < 0) die("asprintf failed"); + if (asprintf(&statusFIFO, "%s/cmd-%s-status", share, procUUID) < 0) + die("asprintf failed"); int fd = open(ctlFIFO, O_WRONLY); if (fd < 0) die("open failed"); @@ -304,25 +317,33 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) if (len_written < 0) die("write failed"); close(fd); + if (setpgrp() < 0) + die("setpgrp failed"); + timeout_msg = "sentinel did not set up FIFOs within 1 second"; struct timespec ts_10ms; ts_10ms.tv_sec = 0; ts_10ms.tv_nsec = 1000 * 1000 * 10; - int mode; pid_t pid = fork(); if (pid < 0) die("fork failed"); else if (pid == 0) { dataFIFO = inputFIFO; - timeout_msg = "sentinel did not set up input FIFO within 1 second"; - mode = O_WRONLY; } else { - dataFIFO = outputFIFO; - timeout_msg = "sentinel did not set up output FIFO within 1 second"; - mode = O_RDONLY; + pid = fork(); + if (pid < 0) + die("fork failed"); + else if (pid == 0) { + dataFIFO = outputFIFO; + } else { + dataFIFO = statusFIFO; + } + } + if (dataFIFO != statusFIFO) { + signal(SIGALRM, wait_alarm_group); + alarm(1); } - signal(SIGALRM, wait_alarm); - alarm(1); while (1) { + int mode = dataFIFO == inputFIFO ? O_WRONLY : O_RDONLY; fd = open(dataFIFO, mode); if (fd >= 0) break; @@ -334,7 +355,7 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) } signal(SIGALRM, SIG_IGN); char buf[1024]; - if (pid == 0) { + if (dataFIFO == inputFIFO) { while ((len = read(STDIN_FILENO, buf, 1024)) > 0) { char *ptr = buf; while (len > 0) { @@ -345,7 +366,9 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) ptr += len_written; } } - } else { + if (len < 0) + die("read failed"); + } else if (dataFIFO == outputFIFO) { while ((len = read(fd, buf, 1024)) > 0) { fwrite(buf, 1, len, stdout); if (ferror(stdout)) @@ -353,9 +376,28 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) if (feof(stdout)) break; } + if (len < 0) + die("read failed"); + } else { + char line[1024]; + char *ptr = line; + int len; + while ((len = read(fd, ptr, 1023 - (ptr - line))) > 0) { + ptr += len; + } + if (len < 0) + die("read failed"); + *ptr = '\0'; + char *endptr; + long status = strtol(line, &endptr, 10); + if (*endptr != '\n') + die("strtol failed"); + if (signal(SIGTERM, SIG_IGN) == SIG_ERR) + die("signal failed"); + if (kill(0, SIGTERM) < 0) + die("kill failed"); + exit(status); } - if (len < 0) - die("read failed"); } int main(int argc, char **argv)