summaryrefslogtreecommitdiff
path: root/sandbox-systrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox-systrace.c')
-rw-r--r--sandbox-systrace.c111
1 files changed, 39 insertions, 72 deletions
diff --git a/sandbox-systrace.c b/sandbox-systrace.c
index 04f54a3b6..2d16a627f 100644
--- a/sandbox-systrace.c
+++ b/sandbox-systrace.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sandbox-systrace.c,v 1.4 2011/07/29 14:42:45 djm 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 *
@@ -17,22 +17,21 @@
17 17
18#include "includes.h" 18#include "includes.h"
19 19
20#include <sys/types.h>
21
22#include "ssh-sandbox.h"
23
24#ifdef SANDBOX_SYSTRACE 20#ifdef SANDBOX_SYSTRACE
25 21
22#include <sys/types.h>
26#include <sys/param.h> 23#include <sys/param.h>
27#include <sys/ioctl.h> 24#include <sys/ioctl.h>
28#include <sys/syscall.h> 25#include <sys/syscall.h>
29#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h>
30 28
31#include <dev/systrace.h> 29#include <dev/systrace.h>
32 30
33#include <errno.h> 31#include <errno.h>
34#include <fcntl.h> 32#include <fcntl.h>
35#include <limits.h> 33#include <limits.h>
34#include <signal.h>
36#include <stdarg.h> 35#include <stdarg.h>
37#include <stdio.h> 36#include <stdio.h>
38#include <stdlib.h> 37#include <stdlib.h>
@@ -41,6 +40,7 @@
41 40
42#include "atomicio.h" 41#include "atomicio.h"
43#include "log.h" 42#include "log.h"
43#include "ssh-sandbox.h"
44#include "xmalloc.h" 44#include "xmalloc.h"
45 45
46struct sandbox_policy { 46struct sandbox_policy {
@@ -60,6 +60,7 @@ static const struct sandbox_policy preauth_policy[] = {
60 { SYS_madvise, SYSTR_POLICY_PERMIT }, 60 { SYS_madvise, SYSTR_POLICY_PERMIT },
61 { SYS_mmap, SYSTR_POLICY_PERMIT }, 61 { SYS_mmap, SYSTR_POLICY_PERMIT },
62 { SYS_mprotect, SYSTR_POLICY_PERMIT }, 62 { SYS_mprotect, SYSTR_POLICY_PERMIT },
63 { SYS_mquery, SYSTR_POLICY_PERMIT },
63 { SYS_poll, SYSTR_POLICY_PERMIT }, 64 { SYS_poll, SYSTR_POLICY_PERMIT },
64 { SYS_munmap, SYSTR_POLICY_PERMIT }, 65 { SYS_munmap, SYSTR_POLICY_PERMIT },
65 { SYS_read, SYSTR_POLICY_PERMIT }, 66 { SYS_read, SYSTR_POLICY_PERMIT },
@@ -70,69 +71,60 @@ static const struct sandbox_policy preauth_policy[] = {
70}; 71};
71 72
72struct ssh_sandbox { 73struct ssh_sandbox {
73 int child_sock;
74 int parent_sock;
75 int systrace_fd; 74 int systrace_fd;
76 pid_t child_pid; 75 pid_t child_pid;
76 void (*osigchld)(int);
77}; 77};
78 78
79static int 79struct ssh_sandbox *
80sandbox_systrace_probe(void) 80ssh_sandbox_init(void)
81{
82 return 1;
83}
84
85static void *
86sandbox_systrace_init(void)
87{ 81{
88 struct ssh_sandbox *box; 82 struct ssh_sandbox *box;
89 int s[2];
90 83
91 debug3("%s: preparing systrace sandbox", __func__); 84 debug3("%s: preparing systrace sandbox", __func__);
92 box = xcalloc(1, sizeof(*box)); 85 box = xcalloc(1, sizeof(*box));
93 if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1)
94 fatal("%s: socketpair: %s", __func__, strerror(errno));
95 box->child_sock = s[0];
96 box->parent_sock = s[1];
97 box->systrace_fd = -1; 86 box->systrace_fd = -1;
98 box->child_pid = 0; 87 box->child_pid = 0;
88 box->osigchld = signal(SIGCHLD, SIG_IGN);
99 89
100 return box; 90 return box;
101} 91}
102 92
103static void 93void
104sandbox_systrace_child(void *vbox) 94ssh_sandbox_child(struct ssh_sandbox *box)
105{ 95{
106 struct ssh_sandbox *box = vbox;
107 char whatever = 0;
108
109 close(box->parent_sock);
110 /* Signal parent that we are ready */
111 debug3("%s: ready", __func__); 96 debug3("%s: ready", __func__);
112 if (atomicio(vwrite, box->child_sock, &whatever, 1) != 1) 97 signal(SIGCHLD, box->osigchld);
113 fatal("%s: write: %s", __func__, strerror(errno)); 98 if (kill(getpid(), SIGSTOP) != 0)
114 /* Wait for parent to signal for us to go */ 99 fatal("%s: kill(%d, SIGSTOP)", __func__, getpid());
115 if (atomicio(read, box->child_sock, &whatever, 1) != 1)
116 fatal("%s: read: %s", __func__, strerror(errno));
117 debug3("%s: started", __func__); 100 debug3("%s: started", __func__);
118 close(box->child_sock);
119} 101}
120 102
121static void 103static void
122sandbox_systrace_parent(struct ssh_sandbox *box, pid_t child_pid, 104ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
123 const struct sandbox_policy *allowed_syscalls) 105 const struct sandbox_policy *allowed_syscalls)
124{ 106{
125 int dev_systrace, i, j, found; 107 int dev_systrace, i, j, found, status;
126 char whatever = 0; 108 pid_t pid;
127 struct systrace_policy policy; 109 struct systrace_policy policy;
128 110
111 /* Wait for the child to send itself a SIGSTOP */
129 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);
130 box->child_pid = child_pid; 127 box->child_pid = child_pid;
131 close(box->child_sock);
132 /* Wait for child to signal that it is ready */
133 if (atomicio(read, box->parent_sock, &whatever, 1) != 1)
134 fatal("%s: read: %s", __func__, strerror(errno));
135 debug3("%s: child %ld ready", __func__, (long)child_pid);
136 128
137 /* Set up systracing of child */ 129 /* Set up systracing of child */
138 if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1) 130 if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1)
@@ -183,16 +175,13 @@ sandbox_systrace_parent(struct ssh_sandbox *box, pid_t child_pid,
183 175
184 /* Signal the child to start running */ 176 /* Signal the child to start running */
185 debug3("%s: start child %ld", __func__, (long)child_pid); 177 debug3("%s: start child %ld", __func__, (long)child_pid);
186 if (atomicio(vwrite, box->parent_sock, &whatever, 1) != 1) 178 if (kill(box->child_pid, SIGCONT) != 0)
187 fatal("%s: write: %s", __func__, strerror(errno)); 179 fatal("%s: kill(%d, SIGCONT)", __func__, box->child_pid);
188 close(box->parent_sock);
189} 180}
190 181
191static void 182void
192sandbox_systrace_parent_finish(void *vbox) 183ssh_sandbox_parent_finish(struct ssh_sandbox *box)
193{ 184{
194 struct ssh_sandbox *box = vbox;
195
196 /* Closing this before the child exits will terminate it */ 185 /* Closing this before the child exits will terminate it */
197 close(box->systrace_fd); 186 close(box->systrace_fd);
198 187
@@ -200,32 +189,10 @@ sandbox_systrace_parent_finish(void *vbox)
200 debug3("%s: finished", __func__); 189 debug3("%s: finished", __func__);
201} 190}
202 191
203static void 192void
204sandbox_systrace_parent_preauth(void *vbox, pid_t child_pid) 193ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
205{ 194{
206 struct ssh_sandbox *box = vbox;
207
208 ssh_sandbox_parent(box, child_pid, preauth_policy); 195 ssh_sandbox_parent(box, child_pid, preauth_policy);
209} 196}
210 197
211Sandbox ssh_sandbox_systrace = {
212 "systrace",
213 sandbox_systrace_probe,
214 sandbox_systrace_init,
215 sandbox_systrace_child,
216 sandbox_systrace_parent_finish,
217 sandbox_systrace_parent_preauth
218};
219
220#else /* !SANDBOX_SYSTRACE */
221
222Sandbox ssh_sandbox_systrace = {
223 "systrace",
224 NULL,
225 NULL,
226 NULL,
227 NULL,
228 NULL
229};
230
231#endif /* SANDBOX_SYSTRACE */ 198#endif /* SANDBOX_SYSTRACE */