diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2012-06-30 14:35:10 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2012-06-30 14:35:10 +0000 |
commit | 41fc90c12d4733d36be15546cee99c4611bcaf51 (patch) | |
tree | af629fa90ea57f3aa826377188282e695490d006 /usr.bin/ssh | |
parent | 1284c0487c9e040773fdc5d6969c8886a4019eb8 (diff) |
fix a during the load of the sandbox policies (child can still make
the read-syscall and wait forever for systrace-answers) by replacing
the read/write synchronisation with SIGSTOP/SIGCONT;
report and help hshoexer@; ok djm@, dtucker@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r-- | usr.bin/ssh/sandbox-systrace.c | 55 | ||||
-rw-r--r-- | usr.bin/ssh/sshd.c | 4 |
2 files changed, 29 insertions, 30 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 diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c index 741b8513556..383920d71a9 100644 --- a/usr.bin/ssh/sshd.c +++ b/usr.bin/ssh/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.391 2012/05/13 01:42:32 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.392 2012/06/30 14:35:09 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -630,9 +630,9 @@ privsep_preauth(Authctxt *authctxt) } else if (pid != 0) { debug2("Network child is on pid %ld", (long)pid); + pmonitor->m_pid = pid; if (box != NULL) ssh_sandbox_parent_preauth(box, pid); - pmonitor->m_pid = pid; monitor_child_preauth(authctxt, pmonitor); /* Sync memory */ |