diff options
Diffstat (limited to 'usr.bin/ssh/sandbox-systrace.c')
-rw-r--r-- | usr.bin/ssh/sandbox-systrace.c | 55 |
1 files changed, 27 insertions, 28 deletions
diff --git a/usr.bin/ssh/sandbox-systrace.c b/usr.bin/ssh/sandbox-systrace.c index 5c699890cc6..ff21fcbcc65 100644 --- a/usr.bin/ssh/sandbox-systrace.c +++ b/usr.bin/ssh/sandbox-systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sandbox-systrace.c,v 1.5 2012/06/26 11:02:30 dtucker Exp $ */ +/* $OpenBSD: sandbox-systrace.c,v 1.6 2012/06/30 14:35:09 markus Exp $ */ /* * Copyright (c) 2011 Damien Miller <djm@mindrot.org> * @@ -20,12 +20,14 @@ #include <sys/ioctl.h> #include <sys/syscall.h> #include <sys/socket.h> +#include <sys/wait.h> #include <dev/systrace.h> #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <signal.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -65,26 +67,21 @@ static const struct sandbox_policy preauth_policy[] = { }; struct ssh_sandbox { - int child_sock; - int parent_sock; int systrace_fd; pid_t child_pid; + void (*osigchld)(int); }; struct ssh_sandbox * ssh_sandbox_init(void) { struct ssh_sandbox *box; - int s[2]; debug3("%s: preparing systrace sandbox", __func__); box = xcalloc(1, sizeof(*box)); - if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) - fatal("%s: socketpair: %s", __func__, strerror(errno)); - box->child_sock = s[0]; - box->parent_sock = s[1]; box->systrace_fd = -1; box->child_pid = 0; + box->osigchld = signal(SIGCHLD, SIG_IGN); return box; } @@ -92,35 +89,38 @@ ssh_sandbox_init(void) void ssh_sandbox_child(struct ssh_sandbox *box) { - char whatever = 0; - - close(box->parent_sock); - /* Signal parent that we are ready */ debug3("%s: ready", __func__); - if (atomicio(vwrite, box->child_sock, &whatever, 1) != 1) - fatal("%s: write: %s", __func__, strerror(errno)); - /* Wait for parent to signal for us to go */ - if (atomicio(read, box->child_sock, &whatever, 1) != 1) - fatal("%s: read: %s", __func__, strerror(errno)); + signal(SIGCHLD, box->osigchld); + if (kill(getpid(), SIGSTOP) != 0) + fatal("%s: kill(%d, SIGSTOP)", __func__, getpid()); debug3("%s: started", __func__); - close(box->child_sock); } static void ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid, const struct sandbox_policy *allowed_syscalls) { - int dev_systrace, i, j, found; - char whatever = 0; + int dev_systrace, i, j, found, status; + pid_t pid; struct systrace_policy policy; + /* Wait for the child to send itself a SIGSTOP */ debug3("%s: wait for child %ld", __func__, (long)child_pid); + do { + pid = waitpid(child_pid, &status, WUNTRACED); + } while (pid == -1 && errno == EINTR); + signal(SIGCHLD, box->osigchld); + if (!WIFSTOPPED(status)) { + if (WIFSIGNALED(status)) + fatal("%s: child terminated with signal %d", + __func__, WTERMSIG(status)); + if (WIFEXITED(status)) + fatal("%s: child exited with status %d", + __func__, WEXITSTATUS(status)); + fatal("%s: child not stopped", __func__); + } + debug3("%s: child %ld stopped", __func__, (long)child_pid); box->child_pid = child_pid; - close(box->child_sock); - /* Wait for child to signal that it is ready */ - if (atomicio(read, box->parent_sock, &whatever, 1) != 1) - fatal("%s: read: %s", __func__, strerror(errno)); - debug3("%s: child %ld ready", __func__, (long)child_pid); /* Set up systracing of child */ if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1) @@ -171,9 +171,8 @@ ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid, /* Signal the child to start running */ debug3("%s: start child %ld", __func__, (long)child_pid); - if (atomicio(vwrite, box->parent_sock, &whatever, 1) != 1) - fatal("%s: write: %s", __func__, strerror(errno)); - close(box->parent_sock); + if (kill(box->child_pid, SIGCONT) != 0) + fatal("%s: kill(%d, SIGCONT)", __func__, box->child_pid); } void |