From 712b9022fadd899094694f2bb17164514768af57 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 11 Jan 2016 18:16:27 +0900 Subject: pass stdout/stderr with pipe --- sandbox/sandbox.c | 61 ++++++++++++++++++++++++++++++++++++++----------------- sandbox/seccomp.c | 6 ++++-- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/sandbox/sandbox.c b/sandbox/sandbox.c index 943c3aa..5b2365b 100644 --- a/sandbox/sandbox.c +++ b/sandbox/sandbox.c @@ -96,26 +96,7 @@ get_arg(pid_t pid, int i) static enum poe_handler_result handle_syscall(pid_t pid, int syscalln) { - long arg1; switch (syscalln) { - case SYS_write: - arg1 = get_arg(pid, 1); - if (arg1 == 1 || arg1 == 2) { - char *pp = (char *)get_arg(pid, 2); - int count = (int)get_arg(pid, 3); - char fd = (char)arg1; - fwrite(&fd, sizeof(fd), 1, stdout); - fwrite(&count, sizeof(count), 1, stdout); - for (int k = 0; k < count; k++, pp++) { - char d = (char)ptrace(PTRACE_PEEKDATA, pid, pp); - fwrite(&d, sizeof(d), 1, stdout); - } - ptrace(PTRACE_POKEUSER, pid, sizeof(long) * RAX, count); - return POE_HANDLED; - } else { - return POE_ALLOWED; - } - break; } return POE_PROHIBITED; } @@ -209,6 +190,30 @@ timer_handler(sd_event_source *es, uint64_t usec, void *vmpid) return 0; } +static int +stdout_handler(sd_event_source *es, int fd, uint32_t revents, void *vorig_fd) +{ + (void)es; (void)revents; + int orig_fd = *(int *)vorig_fd; + char buf[BUFSIZ]; + int n; + + n = (int)read(fd, buf, sizeof(buf)); + if (n < 0) { + if (errno == EAGAIN) { + return 0; + } else { + ERROR("read() failed"); + } + } else { + if (write(STDOUT_FILENO, &orig_fd, sizeof(orig_fd)) < 0) ERROR("write() failed"); + if (write(STDOUT_FILENO, &n, sizeof(n)) < 0) ERROR("write() failed"); + if (write(STDOUT_FILENO, buf, (size_t)n) < 0) ERROR("write() failed"); + } + + return 0; +} + int main(int argc, char *argv[]) { @@ -225,11 +230,22 @@ main(int argc, char *argv[]) sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &omask); + int stdout_fd[2], stderr_fd[2]; + if (pipe(stdout_fd) == -1) ERROR("pipe() failed"); + if (pipe(stderr_fd) == -1) ERROR("pipe() failed"); + // TODO: CLONE_NEWUSER pid_t pid = (pid_t)syscall(SYS_clone, SIGCHLD | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNET, 0); if (pid == -1) { ERROR("clone() failed"); } else if (pid == 0) { + dup2(stdout_fd[1], STDOUT_FILENO); + close(stdout_fd[0]); + close(stdout_fd[1]); + dup2(stderr_fd[1], STDERR_FILENO); + close(stderr_fd[0]); + close(stderr_fd[1]); + sigprocmask(SIG_SETMASK, &omask, NULL); child(root, argc - 4, argv + 4, prog); } else { @@ -244,6 +260,13 @@ main(int argc, char *argv[]) if (rc < 0) ERROR("sd_event_now() failed"); rc = sd_event_add_time(event, NULL, CLOCK_MONOTONIC, now + POE_TIME_LIMIT, 0, timer_handler, &pid); if (rc < 0) ERROR("sd_event_add_time() failed"); + int stdout_fileno = STDOUT_FILENO; + rc = sd_event_add_io(event, NULL, stdout_fd[0], EPOLLIN, stdout_handler, &stdout_fileno); + if (rc < 0) ERROR("sd_event_add_io() failed"); + int stderr_fileno = STDERR_FILENO; + rc = sd_event_add_io(event, NULL, stderr_fd[0], EPOLLIN, stdout_handler, &stderr_fileno); + if (rc < 0) ERROR("sd_event_add_io() failed"); + rc = ptrace(PTRACE_SEIZE, pid, NULL, PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACESECCOMP | PTRACE_O_TRACEVFORK); if (rc < 0) ERROR("ptrace(PTRACE_SEIZE, ) failed"); diff --git a/sandbox/seccomp.c b/sandbox/seccomp.c index 9814874..1c20b53 100644 --- a/sandbox/seccomp.c +++ b/sandbox/seccomp.c @@ -75,8 +75,8 @@ static const struct syscall_rule syscall_rules[] = { RULE(read, ALLOW), RULE(readv, ALLOW), RULE(pread64, ALLOW), - RULE(write, TRACE(1)), - RULE(writev, ERRNO(ENOSYS)), // TODO + RULE(write, ALLOW), + RULE(writev, ALLOW), RULE(pwrite64, ALLOW), RULE(lstat, ALLOW), RULE(fstat, ALLOW), @@ -87,6 +87,8 @@ static const struct syscall_rule syscall_rules[] = { RULE(faccessat, ALLOW), RULE(unlinkat, ALLOW), RULE(fchdir, ALLOW), + RULE(getpeername, ALLOW), + RULE(syslog, ERRNO(EPERM)), }; #undef RULE static const int syscall_rules_count = sizeof(syscall_rules) / sizeof(struct syscall_rule); -- cgit v1.2.3