diff options
Diffstat (limited to 'sandbox-seccomp-filter.c')
-rw-r--r-- | sandbox-seccomp-filter.c | 93 |
1 files changed, 24 insertions, 69 deletions
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c index a564b1316..ef2b13c4f 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c | |||
@@ -35,15 +35,11 @@ | |||
35 | 35 | ||
36 | #include "includes.h" | 36 | #include "includes.h" |
37 | 37 | ||
38 | #include <sys/types.h> | ||
39 | |||
40 | #include "ssh-sandbox.h" | ||
41 | |||
42 | #ifdef SANDBOX_SECCOMP_FILTER | 38 | #ifdef SANDBOX_SECCOMP_FILTER |
43 | 39 | ||
40 | #include <sys/types.h> | ||
44 | #include <sys/resource.h> | 41 | #include <sys/resource.h> |
45 | #include <sys/prctl.h> | 42 | #include <sys/prctl.h> |
46 | #include <sys/wait.h> | ||
47 | 43 | ||
48 | #include <linux/audit.h> | 44 | #include <linux/audit.h> |
49 | #include <linux/filter.h> | 45 | #include <linux/filter.h> |
@@ -61,6 +57,7 @@ | |||
61 | #include <unistd.h> | 57 | #include <unistd.h> |
62 | 58 | ||
63 | #include "log.h" | 59 | #include "log.h" |
60 | #include "ssh-sandbox.h" | ||
64 | #include "xmalloc.h" | 61 | #include "xmalloc.h" |
65 | 62 | ||
66 | /* Linux seccomp_filter sandbox */ | 63 | /* Linux seccomp_filter sandbox */ |
@@ -125,33 +122,8 @@ struct ssh_sandbox { | |||
125 | pid_t child_pid; | 122 | pid_t child_pid; |
126 | }; | 123 | }; |
127 | 124 | ||
128 | static int | 125 | struct ssh_sandbox * |
129 | sandbox_seccomp_filter_probe(void) | 126 | ssh_sandbox_init(void) |
130 | { | ||
131 | int status; | ||
132 | pid_t pid; | ||
133 | |||
134 | pid = fork(); | ||
135 | if (pid == -1) { | ||
136 | fatal("fork of seccomp_filter probe child failed"); | ||
137 | } else if (pid != 0) { | ||
138 | /* parent */ | ||
139 | while (waitpid(pid, &status, 0) < 0) { | ||
140 | if (errno == EINTR) | ||
141 | continue; | ||
142 | fatal("%s: waitpid: %s", __func__, strerror(errno)); | ||
143 | } | ||
144 | return (WIFEXITED(status) && WEXITSTATUS(status) == 0); | ||
145 | } else { | ||
146 | /* child */ | ||
147 | errno = 0; | ||
148 | prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0); | ||
149 | _exit(errno == EFAULT ? 0 : 1); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | static void * | ||
154 | sandbox_seccomp_filter_init(void) | ||
155 | { | 127 | { |
156 | struct ssh_sandbox *box; | 128 | struct ssh_sandbox *box; |
157 | 129 | ||
@@ -171,8 +143,7 @@ extern struct monitor *pmonitor; | |||
171 | void mm_log_handler(LogLevel level, const char *msg, void *ctx); | 143 | void mm_log_handler(LogLevel level, const char *msg, void *ctx); |
172 | 144 | ||
173 | static void | 145 | static void |
174 | sandbox_seccomp_filter_violation(int signum, siginfo_t *info, | 146 | ssh_sandbox_violation(int signum, siginfo_t *info, void *void_context) |
175 | void *void_context) | ||
176 | { | 147 | { |
177 | char msg[256]; | 148 | char msg[256]; |
178 | 149 | ||
@@ -184,7 +155,7 @@ sandbox_seccomp_filter_violation(int signum, siginfo_t *info, | |||
184 | } | 155 | } |
185 | 156 | ||
186 | static void | 157 | static void |
187 | sandbox_seccomp_filter_child_debugging(void) | 158 | ssh_sandbox_child_debugging(void) |
188 | { | 159 | { |
189 | struct sigaction act; | 160 | struct sigaction act; |
190 | sigset_t mask; | 161 | sigset_t mask; |
@@ -194,7 +165,7 @@ sandbox_seccomp_filter_child_debugging(void) | |||
194 | sigemptyset(&mask); | 165 | sigemptyset(&mask); |
195 | sigaddset(&mask, SIGSYS); | 166 | sigaddset(&mask, SIGSYS); |
196 | 167 | ||
197 | act.sa_sigaction = &sandbox_seccomp_filter_violation; | 168 | act.sa_sigaction = &ssh_sandbox_violation; |
198 | act.sa_flags = SA_SIGINFO; | 169 | act.sa_flags = SA_SIGINFO; |
199 | if (sigaction(SIGSYS, &act, NULL) == -1) | 170 | if (sigaction(SIGSYS, &act, NULL) == -1) |
200 | fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno)); | 171 | fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno)); |
@@ -204,10 +175,11 @@ sandbox_seccomp_filter_child_debugging(void) | |||
204 | } | 175 | } |
205 | #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ | 176 | #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ |
206 | 177 | ||
207 | static void | 178 | void |
208 | sandbox_seccomp_filter_child(void *vbox) | 179 | ssh_sandbox_child(struct ssh_sandbox *box) |
209 | { | 180 | { |
210 | struct rlimit rl_zero; | 181 | struct rlimit rl_zero; |
182 | int nnp_failed = 0; | ||
211 | 183 | ||
212 | /* Set rlimits for completeness if possible. */ | 184 | /* Set rlimits for completeness if possible. */ |
213 | rl_zero.rlim_cur = rl_zero.rlim_max = 0; | 185 | rl_zero.rlim_cur = rl_zero.rlim_max = 0; |
@@ -222,52 +194,35 @@ sandbox_seccomp_filter_child(void *vbox) | |||
222 | __func__, strerror(errno)); | 194 | __func__, strerror(errno)); |
223 | 195 | ||
224 | #ifdef SANDBOX_SECCOMP_FILTER_DEBUG | 196 | #ifdef SANDBOX_SECCOMP_FILTER_DEBUG |
225 | sandbox_seccomp_filter_child_debugging(); | 197 | ssh_sandbox_child_debugging(); |
226 | #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ | 198 | #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ |
227 | 199 | ||
228 | debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__); | 200 | debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__); |
229 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) | 201 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { |
230 | fatal("%s: prctl(PR_SET_NO_NEW_PRIVS): %s", | 202 | debug("%s: prctl(PR_SET_NO_NEW_PRIVS): %s", |
231 | __func__, strerror(errno)); | 203 | __func__, strerror(errno)); |
204 | nnp_failed = 1; | ||
205 | } | ||
232 | debug3("%s: attaching seccomp filter program", __func__); | 206 | debug3("%s: attaching seccomp filter program", __func__); |
233 | if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1) | 207 | if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1) |
234 | fatal("%s: prctl(PR_SET_SECCOMP): %s", | 208 | debug("%s: prctl(PR_SET_SECCOMP): %s", |
235 | __func__, strerror(errno)); | 209 | __func__, strerror(errno)); |
210 | else if (nnp_failed) | ||
211 | fatal("%s: SECCOMP_MODE_FILTER activated but " | ||
212 | "PR_SET_NO_NEW_PRIVS failed", __func__); | ||
236 | } | 213 | } |
237 | 214 | ||
238 | static void | 215 | void |
239 | sandbox_seccomp_filter_parent_finish(void *vbox) | 216 | ssh_sandbox_parent_finish(struct ssh_sandbox *box) |
240 | { | 217 | { |
241 | free(vbox); | 218 | free(box); |
242 | debug3("%s: finished", __func__); | 219 | debug3("%s: finished", __func__); |
243 | } | 220 | } |
244 | 221 | ||
245 | static void | 222 | void |
246 | sandbox_seccomp_filter_parent_preauth(void *vbox, pid_t child_pid) | 223 | ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) |
247 | { | 224 | { |
248 | struct ssh_sandbox *box = vbox; | ||
249 | |||
250 | box->child_pid = child_pid; | 225 | box->child_pid = child_pid; |
251 | } | 226 | } |
252 | 227 | ||
253 | Sandbox ssh_sandbox_seccomp_filter = { | ||
254 | "seccomp_filter", | ||
255 | sandbox_seccomp_filter_probe, | ||
256 | sandbox_seccomp_filter_init, | ||
257 | sandbox_seccomp_filter_child, | ||
258 | sandbox_seccomp_filter_parent_finish, | ||
259 | sandbox_seccomp_filter_parent_preauth | ||
260 | }; | ||
261 | |||
262 | #else /* !SANDBOX_SECCOMP_FILTER */ | ||
263 | |||
264 | Sandbox ssh_sandbox_seccomp_filter = { | ||
265 | "seccomp_filter", | ||
266 | NULL, | ||
267 | NULL, | ||
268 | NULL, | ||
269 | NULL, | ||
270 | NULL | ||
271 | }; | ||
272 | |||
273 | #endif /* SANDBOX_SECCOMP_FILTER */ | 228 | #endif /* SANDBOX_SECCOMP_FILTER */ |