OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef SANDBOX_BPF_H__ | 5 #ifndef SANDBOX_BPF_H__ |
6 #define SANDBOX_BPF_H__ | 6 #define SANDBOX_BPF_H__ |
7 | 7 |
8 #include <endian.h> | 8 #include <endian.h> |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <fcntl.h> | 10 #include <fcntl.h> |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, r2) | 137 #define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, r2) |
138 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) | 138 #define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, r3) |
139 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) | 139 #define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, r4) |
140 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) | 140 #define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, r5) |
141 | 141 |
142 #else | 142 #else |
143 #error Unsupported target platform | 143 #error Unsupported target platform |
144 | 144 |
145 #endif | 145 #endif |
146 | 146 |
| 147 #include "sandbox/linux/seccomp-bpf/die.h" |
| 148 |
| 149 |
147 struct arch_seccomp_data { | 150 struct arch_seccomp_data { |
148 int nr; | 151 int nr; |
149 uint32_t arch; | 152 uint32_t arch; |
150 uint64_t instruction_pointer; | 153 uint64_t instruction_pointer; |
151 uint64_t args[6]; | 154 uint64_t args[6]; |
152 }; | 155 }; |
153 | 156 |
154 struct arch_sigsys { | 157 struct arch_sigsys { |
155 void *ip; | 158 void *ip; |
156 int nr; | 159 int nr; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 fnc_(NULL), | 219 fnc_(NULL), |
217 aux_(NULL) { | 220 aux_(NULL) { |
218 switch (err) { | 221 switch (err) { |
219 case SB_INVALID: | 222 case SB_INVALID: |
220 err_ = SECCOMP_RET_INVALID; | 223 err_ = SECCOMP_RET_INVALID; |
221 break; | 224 break; |
222 case SB_ALLOWED: | 225 case SB_ALLOWED: |
223 err_ = SECCOMP_RET_ALLOW; | 226 err_ = SECCOMP_RET_ALLOW; |
224 break; | 227 break; |
225 case SB_INSPECT_ARG_1...SB_INSPECT_ARG_6: | 228 case SB_INSPECT_ARG_1...SB_INSPECT_ARG_6: |
226 die("Not implemented"); | 229 SANDBOX_DIE("Not implemented"); |
227 break; | 230 break; |
228 case 1 ... 4095: | 231 case 1 ... 4095: |
229 err_ = SECCOMP_RET_ERRNO + err; | 232 err_ = SECCOMP_RET_ERRNO + err; |
230 break; | 233 break; |
231 default: | 234 default: |
232 die("Invalid use of ErrorCode object"); | 235 SANDBOX_DIE("Invalid use of ErrorCode object"); |
233 } | 236 } |
234 } | 237 } |
235 | 238 |
236 // If we are wrapping a callback, we must assign a unique id. This id is | 239 // If we are wrapping a callback, we must assign a unique id. This id is |
237 // how the kernel tells us which one of our different SECCOMP_RET_TRAP | 240 // how the kernel tells us which one of our different SECCOMP_RET_TRAP |
238 // cases has been triggered. | 241 // cases has been triggered. |
239 // The getTrapId() function assigns one unique id (starting at 1) for | 242 // The getTrapId() function assigns one unique id (starting at 1) for |
240 // each distinct pair of TrapFnc and auxiliary data. | 243 // each distinct pair of TrapFnc and auxiliary data. |
241 ErrorCode(TrapFnc fnc, const void *aux, int id = 0) : | 244 ErrorCode(TrapFnc fnc, const void *aux, int id = 0) : |
242 id_(id ? id : getTrapId(fnc, aux)), | 245 id_(id ? id : getTrapId(fnc, aux)), |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 // constraints for the system call arguments. In the vast majority of | 307 // constraints for the system call arguments. In the vast majority of |
305 // cases, it will set a "Constraint" that forces a new "errno" value. | 308 // cases, it will set a "Constraint" that forces a new "errno" value. |
306 // But for more complex filters, it is possible to return another mask | 309 // But for more complex filters, it is possible to return another mask |
307 // of SB_INSPECT_ARG_x bits. | 310 // of SB_INSPECT_ARG_x bits. |
308 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, | 311 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, |
309 EvaluateArguments argumentEvaluator); | 312 EvaluateArguments argumentEvaluator); |
310 | 313 |
311 // This is the main public entry point. It finds all system calls that | 314 // This is the main public entry point. It finds all system calls that |
312 // need rewriting, sets up the resources needed by the sandbox, and | 315 // need rewriting, sets up the resources needed by the sandbox, and |
313 // enters Seccomp mode. | 316 // enters Seccomp mode. |
314 static void startSandbox(); | 317 static void startSandbox() { startSandboxInternal(false); } |
315 | 318 |
316 protected: | 319 protected: |
317 // Print an error message and terminate the program. Used for fatal errors. | |
318 static void die(const char *msg) __attribute__((noreturn)) { | |
319 if (msg) { | |
320 #ifndef SECCOMP_BPF_STANDALONE | |
321 if (!dryRun_) { | |
322 // LOG(FATAL) is not neccessarily async-signal safe. It would be | |
323 // better to always use the code for the SECCOMP_BPF_STANDALONE case. | |
324 // But that prevents the logging and reporting infrastructure from | |
325 // picking up sandbox related crashes. | |
326 // For now, in picking between two evils, we decided in favor of | |
327 // LOG(FATAL). In the long run, we probably want to rewrite this code | |
328 // to be async-signal safe. | |
329 LOG(FATAL) << msg; | |
330 } else | |
331 #endif | |
332 { | |
333 // If there is no logging infrastructure in place, we just write error | |
334 // messages to stderr. | |
335 // We also write to stderr, if we are called in a child process from | |
336 // supportsSeccompSandbox(). This makes sure we can actually do the | |
337 // correct logging from the parent process, which is more likely to | |
338 // have access to logging infrastructure. | |
339 if (HANDLE_EINTR(write(2, msg, strlen(msg)))) { } | |
340 if (HANDLE_EINTR(write(2, "\n", 1))) { } | |
341 } | |
342 } | |
343 for (;;) { | |
344 // exit_group() should exit our program. After all, it is defined as a | |
345 // function that doesn't return. But things can theoretically go wrong. | |
346 // Especially, since we are dealing with system call filters. Continuing | |
347 // execution would be very bad in most cases where die() gets called. | |
348 // So, if there is no way for us to ask for the program to exit, the next | |
349 // best thing we can do is to loop indefinitely. Maybe, somebody will | |
350 // notice and file a bug... | |
351 syscall(__NR_exit_group, 1); | |
352 _exit(1); | |
353 } | |
354 } | |
355 | |
356 // Get a file descriptor pointing to "/proc", if currently available. | 320 // Get a file descriptor pointing to "/proc", if currently available. |
357 static int getProcFd() { return proc_fd_; } | 321 static int getProcFd() { return proc_fd_; } |
358 | 322 |
359 private: | 323 private: |
360 friend class Util; | 324 friend class Util; |
361 friend class Verifier; | 325 friend class Verifier; |
362 struct Range { | 326 struct Range { |
363 Range(uint32_t f, uint32_t t, const ErrorCode& e) : | 327 Range(uint32_t f, uint32_t t, const ErrorCode& e) : |
364 from(f), | 328 from(f), |
365 to(t), | 329 to(t), |
(...skipping 15 matching lines...) Expand all Loading... |
381 typedef std::map<std::pair<TrapFnc, const void *>, int> TrapIds; | 345 typedef std::map<std::pair<TrapFnc, const void *>, int> TrapIds; |
382 | 346 |
383 static ErrorCode probeEvaluator(int signo) __attribute__((const)); | 347 static ErrorCode probeEvaluator(int signo) __attribute__((const)); |
384 static void probeProcess(void); | 348 static void probeProcess(void); |
385 static ErrorCode allowAllEvaluator(int signo); | 349 static ErrorCode allowAllEvaluator(int signo); |
386 static void tryVsyscallProcess(void); | 350 static void tryVsyscallProcess(void); |
387 static bool kernelSupportSeccompBPF(int proc_fd); | 351 static bool kernelSupportSeccompBPF(int proc_fd); |
388 static bool RunFunctionInPolicy(void (*function)(), | 352 static bool RunFunctionInPolicy(void (*function)(), |
389 EvaluateSyscall syscallEvaluator, | 353 EvaluateSyscall syscallEvaluator, |
390 int proc_fd); | 354 int proc_fd); |
| 355 static void startSandboxInternal(bool quiet); |
391 static bool isSingleThreaded(int proc_fd); | 356 static bool isSingleThreaded(int proc_fd); |
392 static bool disableFilesystem(); | 357 static bool disableFilesystem(); |
393 static void policySanityChecks(EvaluateSyscall syscallEvaluator, | 358 static void policySanityChecks(EvaluateSyscall syscallEvaluator, |
394 EvaluateArguments argumentEvaluator); | 359 EvaluateArguments argumentEvaluator); |
395 static void installFilter(); | 360 static void installFilter(bool quiet); |
396 static void findRanges(Ranges *ranges); | 361 static void findRanges(Ranges *ranges); |
397 static void emitJumpStatements(Program *program, RetInsns *rets, | 362 static void emitJumpStatements(Program *program, RetInsns *rets, |
398 Ranges::const_iterator start, | 363 Ranges::const_iterator start, |
399 Ranges::const_iterator stop); | 364 Ranges::const_iterator stop); |
400 static void emitReturnStatements(Program *prog, const RetInsns& rets); | 365 static void emitReturnStatements(Program *prog, const RetInsns& rets); |
401 static void sigSys(int nr, siginfo_t *info, void *void_context); | 366 static void sigSys(int nr, siginfo_t *info, void *void_context); |
402 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); | 367 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); |
403 static int getTrapId(TrapFnc fnc, const void *aux); | 368 static int getTrapId(TrapFnc fnc, const void *aux); |
404 | 369 |
405 static bool dryRun_; | |
406 static SandboxStatus status_; | 370 static SandboxStatus status_; |
407 static int proc_fd_; | 371 static int proc_fd_; |
408 static Evaluators evaluators_; | 372 static Evaluators evaluators_; |
409 static Traps *traps_; | 373 static Traps *traps_; |
410 static TrapIds trapIds_; | 374 static TrapIds trapIds_; |
411 static ErrorCode *trapArray_; | 375 static ErrorCode *trapArray_; |
412 static size_t trapArraySize_; | 376 static size_t trapArraySize_; |
413 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); | 377 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); |
414 }; | 378 }; |
415 | 379 |
416 } // namespace | 380 } // namespace |
417 | 381 |
418 #endif // SANDBOX_BPF_H__ | 382 #endif // SANDBOX_BPF_H__ |
OLD | NEW |