aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-01-11 18:16:27 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-01-11 18:16:27 +0900
commit712b9022fadd899094694f2bb17164514768af57 (patch)
tree53b094b69c8573dd35b070f9a93fb731e7c4f3be
parentdceb1224a5a95b0ee0c6ce01d1b91d8d9b26aa99 (diff)
downloadpoe-712b9022fadd899094694f2bb17164514768af57.tar.gz
pass stdout/stderr with pipe
-rw-r--r--sandbox/sandbox.c61
-rw-r--r--sandbox/seccomp.c6
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);