From 31b01855053c515d5dffa866f5098e7207bb2ae5 Mon Sep 17 00:00:00 2001 From: Radon Rosborough Date: Mon, 10 Oct 2022 21:51:25 -0700 Subject: [PATCH] More work on pull and list subcmds --- backend/util.js | 8 ++ system/src/riju-system-privileged.c | 112 ++++++++++++++++++++++++---- 2 files changed, 106 insertions(+), 14 deletions(-) diff --git a/backend/util.js b/backend/util.js index 4e5d7b4..9113ab2 100644 --- a/backend/util.js +++ b/backend/util.js @@ -86,6 +86,14 @@ export async function run(args, log, options) { }); } +export function privilegedList() { + return [rijuSystemPrivileged, "list"]; +} + +export function privilegedPull({ repo, tag }) { + return [rijuSystemPrivileged, "pull", repo, tag]; +} + export function privilegedSession({ uuid, lang }) { const cmdline = [rijuSystemPrivileged, "session", uuid, lang]; if (imageHashes[lang]) { diff --git a/system/src/riju-system-privileged.c b/system/src/riju-system-privileged.c index 524d30f..80544c1 100644 --- a/system/src/riju-system-privileged.c +++ b/system/src/riju-system-privileged.c @@ -30,7 +30,8 @@ void init() { sentinel_bash[sentinel_bash_len - 1] = '\0'; } void die_with_usage() { die("usage:\n" - " riju-system-privileged pull REPO:TAG\n" + " riju-system-privileged list\n" + " riju-system-privileged pull REPO TAG\n" " riju-system-privileged session UUID LANG [IMAGE-HASH]\n" " riju-system-privileged exec UUID CMDLINE...\n" " riju-system-privileged pty UUID CMDLINE...\n" @@ -118,15 +119,26 @@ char *parseImageHash(char *imageHash) return imageHash; } -char *parseImage(char *image) +char *parseRepo(char *repo) { - if (strnlen(image, 1025) > 1024) - die("illegal image name"); - for (char *ptr = image; *ptr; ++ptr) + if (strnlen(repo, 501) > 500) + die("illegal repo name"); + for (char *ptr = repo; *ptr; ++ptr) if (!((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= '0' && *ptr <= '9') || - *ptr == ':' || *ptr == '/' || *ptr == '.' || *ptr == '-')) - die("illegal image name"); - return image; + *ptr == '/' || *ptr == '.' || *ptr == '-' || *ptr == '_')) + die("illegal repo name"); + return repo; +} + +char *parseTag(char *tag) +{ + if (strnlen(tag, 501) > 500) + die("illegal tag name"); + for (char *ptr = tag; *ptr; ++ptr) + if (!((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= '0' && *ptr <= '9') || + *ptr == '.' || *ptr == '-' || *ptr == '_')) + die("illegal tag name"); + return tag; } char *timeout_msg; @@ -144,10 +156,75 @@ void sigalrm_kill_parent(int signum) exit(EXIT_FAILURE); } -void cmd_pull(char *image) +void cmd_list() { + // This command prints a bunch of empty lines because there is no + // way to filter to a desired set of images. Caller is expected to + // remove empty lines because it's easier in JS than C. char *argv[] = { - "docker", "pull", "--", image, NULL, + "docker", + "image", + "ls", + "--format", + "{{ if eq .Repository \"riju\" }}{{ .Tag }}{{ end }}", + NULL, + }; + execvp(argv[0], argv); + die("execvp failed"); +} + +void cmd_pull(char *repo, char *tag) +{ + char *localImage, *remoteImage; + if (asprintf(&remoteImage, "%s:%s", repo, tag) < 0) + die("asprintf failed"); + if (asprintf(&localImage, "riju:%s", tag) < 0) + die("asprintf failed"); + pid_t orig_ppid = getpid(); + pid_t pid = fork(); + if (pid < 0) + die("fork failed"); + else if (pid == 0) { + if (freopen("/dev/null", "w", stdout) == NULL) + die("freopen failed"); + if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) + die("prctl failed"); + if (getppid() != orig_ppid) + exit(EXIT_FAILURE); + char *argv[] = { + "docker", "inspect", "--", localImage, NULL, + }; + execvp(argv[0], argv); + die("execvp failed"); + } + siginfo_t info; + if (waitid(P_PID, pid, &info, WEXITED) < 0) + die("waitid failed"); + if (info.si_status == 0) { + // Image exists already, no need to pull. It is only appropriate + // to use cmd_pull with immutable images. + return; + } + orig_ppid = getpid(); + pid = fork(); + if (pid < 0) + die("fork failed"); + else if (pid == 0) { + if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) + die("prctl failed"); + if (getppid() != orig_ppid) + exit(EXIT_FAILURE); + char *argv[] = { + "docker", "pull", "--", remoteImage, NULL, + }; + execvp(argv[0], argv); + } + if (waitid(P_PID, pid, &info, WEXITED) < 0) + die("waitid failed"); + if (info.si_status != 0) + die("child process failed"); + char *argv[] = { + "docker", "tag", "--", remoteImage, localImage, }; execvp(argv[0], argv); die("execvp failed"); @@ -512,11 +589,18 @@ int main(int argc, char **argv) die("seteuid failed"); if (argc < 2) die_with_usage(); - if (!strcmp(argv[1], "pull")) { - if (argc != 3) + if (!strcmp(argv[1], "list")) { + if (argc != 2) die_with_usage(); - char *image = parseImage(argv[2]); - cmd_pull(image); + cmd_list(); + return 0; + } + if (!strcmp(argv[1], "pull")) { + if (argc != 4) + die_with_usage(); + char *repo = parseRepo(argv[2]); + char *tag = parseTag(argv[3]); + cmd_pull(repo, tag); return 0; } if (!strcmp(argv[1], "session")) {