summaryrefslogtreecommitdiff
path: root/sandbox-systrace.c
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2012-07-02 18:54:31 +1000
committerDarren Tucker <dtucker@zip.com.au>2012-07-02 18:54:31 +1000
commit3b4b2d30219d2ecb1426d2f9339239d32bad7bf6 (patch)
treeacc09756c1777801a7e4345eee6db301dbe1e58a /sandbox-systrace.c
parentecbf14aa53da21aeedc0974e13196fe77cca18f3 (diff)
- markus@cvs.openbsd.org 2012/06/30 14:35:09
[sandbox-systrace.c sshd.c] 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 'sandbox-systrace.c')
-rw-r--r--sandbox-systrace.c55
1 files changed, 27 insertions, 28 deletions
diff --git a/sandbox-systrace.c b/sandbox-systrace.c
index 199b69f44..2d16a627f 100644
--- a/sandbox-systrace.c
+++ b/sandbox-systrace.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sandbox-systrace.c,v 1.5 2012/06/26 11:02:30 dtucker Exp $ */ 1/* $OpenBSD: sandbox-systrace.c,v 1.6 2012/06/30 14:35:09 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -24,12 +24,14 @@
24#include <sys/ioctl.h> 24#include <sys/ioctl.h>
25#include <sys/syscall.h> 25#include <sys/syscall.h>
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h>
27 28
28#include <dev/systrace.h> 29#include <dev/systrace.h>
29 30
30#include <errno.h> 31#include <errno.h>
31#include <fcntl.h> 32#include <fcntl.h>
32#include <limits.h> 33#include <limits.h>
34#include <signal.h>
33#include <stdarg.h> 35#include <stdarg.h>
34#include <stdio.h> 36#include <stdio.h>
35#include <stdlib.h> 37#include <stdlib.h>
@@ -69,26 +71,21 @@ static const struct sandbox_policy preauth_policy[] = {
69}; 71};
70 72
71struct ssh_sandbox { 73struct ssh_sandbox {
72 int child_sock;
73 int parent_sock;
74 int systrace_fd; 74 int systrace_fd;
75 pid_t child_pid; 75 pid_t child_pid;
76 void (*osigchld)(int);
76}; 77};
77 78
78struct ssh_sandbox * 79struct ssh_sandbox *
79ssh_sandbox_init(void) 80ssh_sandbox_init(void)
80{ 81{
81 struct ssh_sandbox *box; 82 struct ssh_sandbox *box;
82 int s[2];
83 83
84 debug3("%s: preparing systrace sandbox", __func__); 84 debug3("%s: preparing systrace sandbox", __func__);
85 box = xcalloc(1, sizeof(*box)); 85 box = xcalloc(1, sizeof(*box));
86 if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1)
87 fatal("%s: socketpair: %s", __func__, strerror(errno));
88 box->child_sock = s[0];
89 box->parent_sock = s[1];
90 box->systrace_fd = -1; 86 box->systrace_fd = -1;
91 box->child_pid = 0; 87 box->child_pid = 0;
88 box->osigchld = signal(SIGCHLD, SIG_IGN);
92 89
93 return box; 90 return box;
94} 91}
@@ -96,35 +93,38 @@ ssh_sandbox_init(void)
96void 93void
97ssh_sandbox_child(struct ssh_sandbox *box) 94ssh_sandbox_child(struct ssh_sandbox *box)
98{ 95{
99 char whatever = 0;
100
101 close(box->parent_sock);
102 /* Signal parent that we are ready */
103 debug3("%s: ready", __func__); 96 debug3("%s: ready", __func__);
104 if (atomicio(vwrite, box->child_sock, &whatever, 1) != 1) 97 signal(SIGCHLD, box->osigchld);
105 fatal("%s: write: %s", __func__, strerror(errno)); 98 if (kill(getpid(), SIGSTOP) != 0)
106 /* Wait for parent to signal for us to go */ 99 fatal("%s: kill(%d, SIGSTOP)", __func__, getpid());
107 if (atomicio(read, box->child_sock, &whatever, 1) != 1)
108 fatal("%s: read: %s", __func__, strerror(errno));
109 debug3("%s: started", __func__); 100 debug3("%s: started", __func__);
110 close(box->child_sock);
111} 101}
112 102
113static void 103static void
114ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid, 104ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
115 const struct sandbox_policy *allowed_syscalls) 105 const struct sandbox_policy *allowed_syscalls)
116{ 106{
117 int dev_systrace, i, j, found; 107 int dev_systrace, i, j, found, status;
118 char whatever = 0; 108 pid_t pid;
119 struct systrace_policy policy; 109 struct systrace_policy policy;
120 110
111 /* Wait for the child to send itself a SIGSTOP */
121 debug3("%s: wait for child %ld", __func__, (long)child_pid); 112 debug3("%s: wait for child %ld", __func__, (long)child_pid);
113 do {
114 pid = waitpid(child_pid, &status, WUNTRACED);
115 } while (pid == -1 && errno == EINTR);
116 signal(SIGCHLD, box->osigchld);
117 if (!WIFSTOPPED(status)) {
118 if (WIFSIGNALED(status))
119 fatal("%s: child terminated with signal %d",
120 __func__, WTERMSIG(status));
121 if (WIFEXITED(status))
122 fatal("%s: child exited with status %d",
123 __func__, WEXITSTATUS(status));
124 fatal("%s: child not stopped", __func__);
125 }
126 debug3("%s: child %ld stopped", __func__, (long)child_pid);
122 box->child_pid = child_pid; 127 box->child_pid = child_pid;
123 close(box->child_sock);
124 /* Wait for child to signal that it is ready */
125 if (atomicio(read, box->parent_sock, &whatever, 1) != 1)
126 fatal("%s: read: %s", __func__, strerror(errno));
127 debug3("%s: child %ld ready", __func__, (long)child_pid);
128 128
129 /* Set up systracing of child */ 129 /* Set up systracing of child */
130 if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1) 130 if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1)
@@ -175,9 +175,8 @@ ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
175 175
176 /* Signal the child to start running */ 176 /* Signal the child to start running */
177 debug3("%s: start child %ld", __func__, (long)child_pid); 177 debug3("%s: start child %ld", __func__, (long)child_pid);
178 if (atomicio(vwrite, box->parent_sock, &whatever, 1) != 1) 178 if (kill(box->child_pid, SIGCONT) != 0)
179 fatal("%s: write: %s", __func__, strerror(errno)); 179 fatal("%s: kill(%d, SIGCONT)", __func__, box->child_pid);
180 close(box->parent_sock);
181} 180}
182 181
183void 182void