diff options
Diffstat (limited to 'sandbox-systrace.c')
-rw-r--r-- | sandbox-systrace.c | 111 |
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 | ||
46 | struct sandbox_policy { | 46 | struct 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 | ||
72 | struct ssh_sandbox { | 73 | struct 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 | ||
79 | static int | 79 | struct ssh_sandbox * |
80 | sandbox_systrace_probe(void) | 80 | ssh_sandbox_init(void) |
81 | { | ||
82 | return 1; | ||
83 | } | ||
84 | |||
85 | static void * | ||
86 | sandbox_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 | ||
103 | static void | 93 | void |
104 | sandbox_systrace_child(void *vbox) | 94 | ssh_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 | ||
121 | static void | 103 | static void |
122 | sandbox_systrace_parent(struct ssh_sandbox *box, pid_t child_pid, | 104 | ssh_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 | ||
191 | static void | 182 | void |
192 | sandbox_systrace_parent_finish(void *vbox) | 183 | ssh_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 | ||
203 | static void | 192 | void |
204 | sandbox_systrace_parent_preauth(void *vbox, pid_t child_pid) | 193 | ssh_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 | ||
211 | Sandbox 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 | |||
222 | Sandbox 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 */ |