diff options
author | Darren Tucker <dtucker@zip.com.au> | 2012-07-02 18:54:31 +1000 |
---|---|---|
committer | Darren Tucker <dtucker@zip.com.au> | 2012-07-02 18:54:31 +1000 |
commit | 3b4b2d30219d2ecb1426d2f9339239d32bad7bf6 (patch) | |
tree | acc09756c1777801a7e4345eee6db301dbe1e58a | |
parent | ecbf14aa53da21aeedc0974e13196fe77cca18f3 (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@
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | sandbox-systrace.c | 55 | ||||
-rw-r--r-- | sshd.c | 4 |
3 files changed, 35 insertions, 30 deletions
@@ -4,6 +4,12 @@ | |||
4 | [ssh_config.5 sshd_config.5] | 4 | [ssh_config.5 sshd_config.5] |
5 | match the documented MAC order of preference to the actual one; | 5 | match the documented MAC order of preference to the actual one; |
6 | ok dtucker@ | 6 | ok dtucker@ |
7 | - markus@cvs.openbsd.org 2012/06/30 14:35:09 | ||
8 | [sandbox-systrace.c sshd.c] | ||
9 | fix a during the load of the sandbox policies (child can still make | ||
10 | the read-syscall and wait forever for systrace-answers) by replacing | ||
11 | the read/write synchronisation with SIGSTOP/SIGCONT; | ||
12 | report and help hshoexer@; ok djm@, dtucker@ | ||
7 | 13 | ||
8 | 20120629 | 14 | 20120629 |
9 | - OpenBSD CVS Sync | 15 | - OpenBSD CVS Sync |
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 | ||
71 | struct ssh_sandbox { | 73 | struct 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 | ||
78 | struct ssh_sandbox * | 79 | struct ssh_sandbox * |
79 | ssh_sandbox_init(void) | 80 | ssh_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) | |||
96 | void | 93 | void |
97 | ssh_sandbox_child(struct ssh_sandbox *box) | 94 | ssh_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 | ||
113 | static void | 103 | static void |
114 | ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid, | 104 | ssh_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 | ||
183 | void | 182 | void |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.391 2012/05/13 01:42:32 dtucker Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.392 2012/06/30 14:35:09 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -643,9 +643,9 @@ privsep_preauth(Authctxt *authctxt) | |||
643 | } else if (pid != 0) { | 643 | } else if (pid != 0) { |
644 | debug2("Network child is on pid %ld", (long)pid); | 644 | debug2("Network child is on pid %ld", (long)pid); |
645 | 645 | ||
646 | pmonitor->m_pid = pid; | ||
646 | if (box != NULL) | 647 | if (box != NULL) |
647 | ssh_sandbox_parent_preauth(box, pid); | 648 | ssh_sandbox_parent_preauth(box, pid); |
648 | pmonitor->m_pid = pid; | ||
649 | monitor_child_preauth(authctxt, pmonitor); | 649 | monitor_child_preauth(authctxt, pmonitor); |
650 | 650 | ||
651 | /* Sync memory */ | 651 | /* Sync memory */ |