15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Some headers on Android are missing cdefs: crbug.com/172337. 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (We can't use OS_ANDROID here since build_config.h is not included). 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ANDROID) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/cdefs.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h> 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h> 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h> 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/prctl.h> 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/stat.h> 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/syscall.h> 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/types.h> 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <time.h> 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <unistd.h> 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef SECCOMP_BPF_STANDALONE 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/codegen.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sandbox/linux/seccomp-bpf/syscall.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/syscall_iterator.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/verifier.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using playground2::ErrorCode; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using playground2::Instruction; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using playground2::Sandbox; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using playground2::Trap; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using playground2::arch_seccomp_data; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kExpectedExitCode = 100; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<class T> int popcount(T x); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<> int popcount<unsigned int>(unsigned int x) { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return __builtin_popcount(x); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<> int popcount<unsigned long>(unsigned long x) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return __builtin_popcountl(x); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<> int popcount<unsigned long long>(unsigned long long x) { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return __builtin_popcountll(x); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WriteFailedStderrSetupMessage(int out_fd) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* error_string = strerror(errno); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const char msg[] = "You have reproduced a puzzling issue.\n" 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Please, report to crbug.com/152530!\n" 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Failed to set up stderr: "; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg)-1)) > 0 && error_string && 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE_EINTR(write(out_fd, error_string, strlen(error_string))) > 0 && 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE_EINTR(write(out_fd, "\n", 1))) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We define a really simple sandbox policy. It is just good enough for us 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to tell that the sandbox has actually been activated. 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode ProbeEvaluator(Sandbox *, int sysnum, void *) __attribute__((const)); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode ProbeEvaluator(Sandbox *, int sysnum, void *) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (sysnum) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case __NR_getpid: 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return EPERM so that we can check that the filter actually ran. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ErrorCode(EPERM); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case __NR_exit_group: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow exit() with a non-default return code. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ErrorCode(ErrorCode::ERR_ALLOWED); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make everything else fail in an easily recognizable way. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ErrorCode(EINVAL); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProbeProcess(void) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (syscall(__NR_getpid) < 0 && errno == EPERM) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode AllowAllEvaluator(Sandbox *, int sysnum, void *) { 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!Sandbox::IsValidSyscallNumber(sysnum)) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ErrorCode(ENOSYS); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ErrorCode(ErrorCode::ERR_ALLOWED); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TryVsyscallProcess(void) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_t current_time; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time() is implemented as a vsyscall. With an older glibc, with 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // vsyscall=emulate and some versions of the seccomp BPF patch 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we may get SIGKILL-ed. Detect this! 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (time(¤t_time) != static_cast<time_t>(-1)) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syscall(__NR_exit_group, static_cast<intptr_t>(kExpectedExitCode)); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsSingleThreaded(int proc_fd) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (proc_fd < 0) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cannot determine whether program is single-threaded. Hope for 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the best... 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct stat sb; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int task = -1; 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((task = openat(proc_fd, "self/task", O_RDONLY|O_DIRECTORY)) < 0 || 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fstat(task, &sb) != 0 || 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sb.st_nlink != 3 || 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HANDLE_EINTR(close(task))) { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (task >= 0) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HANDLE_EINTR(close(task))) { } 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsDenied(const ErrorCode& code) { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (code.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_TRAP || 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (code.err() >= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MIN_ERRNO) && 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) code.err() <= (SECCOMP_RET_ERRNO + ErrorCode::ERR_MAX_ERRNO)); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Function that can be passed as a callback function to CodeGen::Traverse(). 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sets the "bool" variable pointed to by "aux". 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckForUnsafeErrorCodes(Instruction *insn, void *aux) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool *is_unsafe = static_cast<bool *>(aux); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!*is_unsafe) { 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (BPF_CLASS(insn->code) == BPF_RET && 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) insn->k > SECCOMP_RET_TRAP && 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) insn->k - SECCOMP_RET_TRAP <= SECCOMP_RET_DATA) { 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ErrorCode& err = 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Trap::ErrorCodeFromTrapId(insn->k & SECCOMP_RET_DATA); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (err.error_type() != ErrorCode::ET_INVALID && !err.safe()) { 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *is_unsafe = true; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A Trap() handler that returns an "errno" value. The value is encoded 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// in the "aux" parameter. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TrapFnc functions report error by following the native kernel convention 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of returning an exit code in the range of -1..-4096. They do not try to 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // set errno themselves. The glibc wrapper that triggered the SIGSYS will 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ultimately do so for us. 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int err = reinterpret_cast<intptr_t>(aux) & SECCOMP_RET_DATA; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -err; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Function that can be passed as a callback function to CodeGen::Traverse(). 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Checks whether the "insn" returns an errno value from a BPF filter. If so, 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// it rewrites the instruction to instead call a Trap() handler that does 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the same thing. "aux" is ignored. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RedirectToUserspace(Instruction *insn, void *aux) { 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When inside an UnsafeTrap() callback, we want to allow all system calls. 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This means, we must conditionally disable the sandbox -- and that's not 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // something that kernel-side BPF filters can do, as they cannot inspect 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any state other than the syscall arguments. 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // But if we redirect all error handlers to user-space, then we can easily 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // make this decision. 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The performance penalty for this extra round-trip to user-space is not 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // actually that bad, as we only ever pay it for denied system calls; and a 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // typical program has very few of these. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sandbox *sandbox = static_cast<Sandbox *>(aux); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (BPF_CLASS(insn->code) == BPF_RET && 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (insn->k & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) insn->k = sandbox->Trap(ReturnErrno, 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<void *>(insn->k & SECCOMP_RET_DATA)).err(); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Stackable wrapper around an Evaluators handler. Changes ErrorCodes 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// returned by a system call evaluator to match the changes made by 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RedirectToUserspace(). "aux" should be pointer to wrapped system call 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// evaluator. 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode RedirectToUserspaceEvalWrapper(Sandbox *sandbox, int sysnum, 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void *aux) { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to replicate the behavior of RedirectToUserspace(), so that our 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verifier can still work correctly. 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sandbox::Evaluators *evaluators = 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<Sandbox::Evaluators *>(aux); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::pair<Sandbox::EvaluateSyscall, void *>& evaluator = 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *evaluators->begin(); 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorCode err = evaluator.first(sandbox, sysnum, evaluator.second); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((err.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return sandbox->Trap(ReturnErrno, 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<void *>(err.err() & SECCOMP_RET_DATA)); 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return err; 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)intptr_t BpfFailure(const struct arch_seccomp_data&, void *aux) { 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE(static_cast<char *>(aux)); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The kernel gives us a sandbox, we turn it into a playground :-) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is version 2 of the playground; version 1 was built on top of 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// pre-BPF seccomp mode. 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace playground2 { 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Sandbox::Sandbox() 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : quiet_(false), 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) proc_fd_(-1), 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) evaluators_(new Evaluators), 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conds_(new Conds) { 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Sandbox::~Sandbox() { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It is generally unsafe to call any memory allocator operations or to even 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // call arbitrary destructors after having installed a new policy. We just 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have no way to tell whether this policy would allow the system calls that 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the constructors can trigger. 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // So, we normally destroy all of our complex state prior to starting the 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sandbox. But this won't happen, if the Sandbox object was created and 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // never actually used to set up a sandbox. So, just in case, we are 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // destroying any remaining state. 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The "if ()" statements are technically superfluous. But let's be explicit 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that we really don't want to run any code, when we already destroyed 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // objects before setting up the sandbox. 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (evaluators_) { 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete evaluators_; 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (conds_) { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete conds_; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Sandbox::IsValidSyscallNumber(int sysnum) { 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SyscallIterator::IsValid(sysnum); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Sandbox::RunFunctionInPolicy(void (*code_in_sandbox)(), 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sandbox::EvaluateSyscall syscall_evaluator, 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void *aux) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Block all signals before forking a child process. This prevents an 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attacker from manipulating our test by sending us an unexpected signal. 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sigset_t old_mask, new_mask; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sigfillset(&new_mask) || 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sigprocmask(SIG_BLOCK, &new_mask, &old_mask)) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("sigprocmask() failed"); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fds[2]; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipe2(fds, O_NONBLOCK|O_CLOEXEC)) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("pipe() failed"); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fds[0] <= 2 || fds[1] <= 2) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Process started without standard file descriptors"); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t pid = fork(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pid < 0) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Die if we cannot fork(). We would probably fail a little later 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // anyway, as the machine is likely very close to running out of 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // memory. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // But what we don't want to do is return "false", as a crafty 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attacker might cause fork() to fail at will and could trick us 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // into running without a sandbox. 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sigprocmask(SIG_SETMASK, &old_mask, NULL); // OK, if it fails 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("fork() failed unexpectedly"); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the child process 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pid) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test a very simple sandbox policy to verify that we can 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // successfully turn on sandboxing. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Die::EnableSimpleExit(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) errno = 0; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(fds[0]))) { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This call to close() has been failing in strange ways. See 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // crbug.com/152530. So we only fail in debug mode now. 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(NDEBUG) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteFailedStderrSetupMessage(fds[1]); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE(NULL); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(dup2(fds[1], 2)) != 2) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stderr could very well be a file descriptor to .xsession-errors, or 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // another file, which could be backed by a file system that could cause 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dup2 to fail while trying to close stderr. It's important that we do 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not fail on trying to close stderr. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If dup2 fails here, we will continue normally, this means that our 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parent won't cause a fatal failure if something writes to stderr in 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this child. 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(NDEBUG) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In DEBUG builds, we still want to get a report. 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WriteFailedStderrSetupMessage(fds[1]); 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE(NULL); 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(fds[1]))) { 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This call to close() has been failing in strange ways. See 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // crbug.com/152530. So we only fail in debug mode now. 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(NDEBUG) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteFailedStderrSetupMessage(fds[1]); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE(NULL); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetSandboxPolicy(syscall_evaluator, aux); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartSandbox(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run our code in the sandbox. 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) code_in_sandbox(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // code_in_sandbox() is not supposed to return here. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE(NULL); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the parent process. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(fds[1]))) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("close() failed"); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sigprocmask(SIG_SETMASK, &old_mask, NULL)) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("sigprocmask() failed"); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(waitpid(pid, &status, 0)) != pid) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("waitpid() failed unexpectedly"); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool rc = WIFEXITED(status) && WEXITSTATUS(status) == kExpectedExitCode; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we fail to support sandboxing, there might be an additional 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error message. If so, this was an entirely unexpected and fatal 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // failure. We should report the failure and somebody must fix 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // things. This is probably a security-critical bug in the sandboxing 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rc) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[4096]; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t len = HANDLE_EINTR(read(fds[0], buf, sizeof(buf) - 1)); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len > 0) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (len > 1 && buf[len-1] == '\n') { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --len; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[len] = '\000'; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE(buf); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(fds[0]))) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("close() failed"); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Sandbox::KernelSupportSeccompBPF() { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunFunctionInPolicy(ProbeProcess, ProbeEvaluator, 0) && 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunFunctionInPolicy(TryVsyscallProcess, AllowAllEvaluator, 0); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Sandbox::SandboxStatus Sandbox::SupportsSeccompSandbox(int proc_fd) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It the sandbox is currently active, we clearly must have support for 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sandboxing. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == STATUS_ENABLED) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status_; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Even if the sandbox was previously available, something might have 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changed in our run-time environment. Check one more time. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == STATUS_AVAILABLE) { 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsSingleThreaded(proc_fd)) { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = STATUS_UNAVAILABLE; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status_; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status_ == STATUS_UNAVAILABLE && IsSingleThreaded(proc_fd)) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All state transitions resulting in STATUS_UNAVAILABLE are immediately 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // preceded by STATUS_AVAILABLE. Furthermore, these transitions all 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happen, if and only if they are triggered by the process being multi- 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threaded. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In other words, if a single-threaded process is currently in the 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // STATUS_UNAVAILABLE state, it is safe to assume that sandboxing is 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually available. 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = STATUS_AVAILABLE; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status_; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have not previously checked for availability of the sandbox or if 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we otherwise don't believe to have a good cached value, we have to 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // perform a thorough check now. 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == STATUS_UNKNOWN) { 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We create our own private copy of a "Sandbox" object. This ensures that 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the object does not have any policies configured, that might interfere 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // with the tests done by "KernelSupportSeccompBPF()". 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Sandbox sandbox; 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // By setting "quiet_ = true" we suppress messages for expected and benign 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // failures (e.g. if the current kernel lacks support for BPF filters). 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sandbox.quiet_ = true; 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sandbox.set_proc_fd(proc_fd); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_ = sandbox.KernelSupportSeccompBPF() 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ? STATUS_AVAILABLE : STATUS_UNSUPPORTED; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As we are performing our tests from a child process, the run-time 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // environment that is visible to the sandbox is always guaranteed to be 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // single-threaded. Let's check here whether the caller is single- 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threaded. Otherwise, we mark the sandbox as temporarily unavailable. 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status_ == STATUS_AVAILABLE && !IsSingleThreaded(proc_fd)) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = STATUS_UNAVAILABLE; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status_; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Sandbox::set_proc_fd(int proc_fd) { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc_fd_ = proc_fd; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Sandbox::StartSandbox() { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status_ == STATUS_UNSUPPORTED || status_ == STATUS_UNAVAILABLE) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Trying to start sandbox, even though it is known to be " 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "unavailable"); 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!evaluators_ || !conds_) { 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("Cannot repeatedly start sandbox. Create a separate Sandbox " 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "object instead."); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proc_fd_ < 0) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc_fd_ = open("/proc", O_RDONLY|O_DIRECTORY); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proc_fd_ < 0) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, continue in degraded mode, if we can't access /proc. 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the future, we might want to tighten this requirement. 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsSingleThreaded(proc_fd_)) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Cannot start sandbox, if process is already multi-threaded"); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We no longer need access to any files in /proc. We want to do this 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before installing the filters, just in case that our policy denies 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // close(). 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proc_fd_ >= 0) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HANDLE_EINTR(close(proc_fd_))) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Failed to close file descriptor for /proc"); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc_fd_ = -1; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Install the filters. 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InstallFilter(); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are now inside the sandbox. 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status_ = STATUS_ENABLED; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Sandbox::PolicySanityChecks(EvaluateSyscall syscall_evaluator, 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *aux) { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SyscallIterator iter(true); !iter.Done(); ) { 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t sysnum = iter.Next(); 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsDenied(syscall_evaluator(this, sysnum, aux))) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Policies should deny system calls that are outside the " 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "expected range (typically MIN_SYSCALL..MAX_SYSCALL)"); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Sandbox::SetSandboxPolicy(EvaluateSyscall syscall_evaluator, void *aux) { 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!evaluators_ || !conds_) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Cannot change policy after sandbox has started"); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PolicySanityChecks(syscall_evaluator, aux); 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) evaluators_->push_back(std::make_pair(syscall_evaluator, aux)); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Sandbox::InstallFilter() { 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We want to be very careful in not imposing any requirements on the 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // policies that are set with SetSandboxPolicy(). This means, as soon as 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the sandbox is active, we shouldn't be relying on libraries that could 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // be making system calls. This, for example, means we should avoid 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // using the heap and we should avoid using STL functions. 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Temporarily copy the contents of the "program" vector into a 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stack-allocated array; and then explicitly destroy that object. 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This makes sure we don't ex- or implicitly call new/delete after we 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // installed the BPF filter program in the kernel. Depending on the 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // system memory allocator that is in effect, these operators can result 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in system calls to things like munmap() or brk(). 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Program *program = AssembleFilter(false /* force_verification */); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct sock_filter bpf[program->size()]; 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct sock_fprog prog = { 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<unsigned short>(program->size()), bpf }; 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(bpf, &(*program)[0], sizeof(bpf)); 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete program; 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Release memory that is no longer needed 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete evaluators_; 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete conds_; 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) evaluators_ = NULL; 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) conds_ = NULL; 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Install BPF filter program 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE(quiet_ ? NULL : "Kernel refuses to enable no-new-privs"); 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE(quiet_ ? NULL : "Kernel refuses to turn on BPF filters"); 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Sandbox::Program *Sandbox::AssembleFilter(bool force_verification) { 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(NDEBUG) 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) force_verification = true; 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify that the user pushed a policy. 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (evaluators_->empty()) { 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("Failed to configure system call filters"); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't handle stacked evaluators, yet. We'll get there eventually 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // though. Hang tight. 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (evaluators_->size() != 1) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Not implemented"); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assemble the BPF filter program. 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CodeGen *gen = new CodeGen(); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gen) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Out of memory"); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the architecture doesn't match SECCOMP_ARCH, disallow the 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system call. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Instruction *tail; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Instruction *head = 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_LD+BPF_W+BPF_ABS, SECCOMP_ARCH_IDX, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tail = 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NULL, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gen->MakeInstruction(BPF_RET+BPF_K, 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Kill("Invalid audit architecture in BPF filter")))); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_unsafe_traps = false; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Evaluate all possible system calls and group their ErrorCodes into 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ranges of identical codes. 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ranges ranges; 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FindRanges(&ranges); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compile the system call ranges to an optimized BPF jumptable 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Instruction *jumptable = 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AssembleJumpTable(gen, ranges.begin(), ranges.end()); 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is at least one UnsafeTrap() in our program, the entire sandbox 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is unsafe. We need to modify the program so that all non- 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SECCOMP_RET_ALLOW ErrorCodes are handled in user-space. This will then 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // allow us to temporarily disable sandboxing rules inside of callbacks to 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // UnsafeTrap(). 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->Traverse(jumptable, CheckForUnsafeErrorCodes, &has_unsafe_traps); 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Grab the system call number, so that we can implement jump tables. 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *load_nr = 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_LD+BPF_W+BPF_ABS, SECCOMP_NR_IDX); 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If our BPF program has unsafe jumps, enable support for them. This 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // test happens very early in the BPF filter program. Even before we 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // consider looking at system call numbers. 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // As support for unsafe jumps essentially defeats all the security 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // measures that the sandbox provides, we print a big warning message -- 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and of course, we make sure to only ever enable this feature if it 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is actually requested by the sandbox policy. 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (has_unsafe_traps) { 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (SandboxSyscall(-1) == -1 && errno == ENOSYS) { 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("Support for UnsafeTrap() has not yet been ported to this " 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "architecture"); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EvaluateSyscall evaluateSyscall = evaluators_->begin()->first; 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void *aux = evaluators_->begin()->second; 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!evaluateSyscall(this, __NR_rt_sigprocmask, aux). 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Equals(ErrorCode(ErrorCode::ERR_ALLOWED)) || 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !evaluateSyscall(this, __NR_rt_sigreturn, aux). 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Equals(ErrorCode(ErrorCode::ERR_ALLOWED)) 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__NR_sigprocmask) 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) || !evaluateSyscall(this, __NR_sigprocmask, aux). 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Equals(ErrorCode(ErrorCode::ERR_ALLOWED)) 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__NR_sigreturn) 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) || !evaluateSyscall(this, __NR_sigreturn, aux). 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Equals(ErrorCode(ErrorCode::ERR_ALLOWED)) 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ) { 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("Invalid seccomp policy; if using UnsafeTrap(), you must " 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "unconditionally allow sigreturn() and sigprocmask()"); 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!Trap::EnableUnsafeTrapsInSigSysHandler()) { 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We should never be able to get here, as UnsafeTrap() should never 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // actually return a valid ErrorCode object unless the user set the 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CHROME_SANDBOX_DEBUGGING environment variable; and therefore, 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // "has_unsafe_traps" would always be false. But better double-check 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // than enabling dangerous code. 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("We'd rather die than enable unsafe traps"); 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->Traverse(jumptable, RedirectToUserspace, this); 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Allow system calls, if they originate from our magic return address 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (which we can query by calling SandboxSyscall(-1)). 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uintptr_t syscall_entry_point = 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<uintptr_t>(SandboxSyscall(-1)); 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t low = static_cast<uint32_t>(syscall_entry_point); 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if __SIZEOF_POINTER__ > 4 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t hi = static_cast<uint32_t>(syscall_entry_point >> 32); 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // BPF cannot do native 64bit comparisons. On 64bit architectures, we 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have to compare both 32bit halves of the instruction pointer. If they 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // match what we expect, we return ERR_ALLOWED. If either or both don't 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // match, we continue evalutating the rest of the sandbox policy. 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *escape_hatch = 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_LD+BPF_W+BPF_ABS, SECCOMP_IP_LSB_IDX, 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, low, 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if __SIZEOF_POINTER__ > 4 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_LD+BPF_W+BPF_ABS, SECCOMP_IP_MSB_IDX, 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, hi, 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_RET+BPF_K, ErrorCode(ErrorCode::ERR_ALLOWED)), 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if __SIZEOF_POINTER__ > 4 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) load_nr)), 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) load_nr)); 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(tail, escape_hatch); 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(tail, load_nr); 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tail = load_nr; 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // On Intel architectures, verify that system call numbers are in the 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // expected number range. The older i386 and x86-64 APIs clear bit 30 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // on all system calls. The newer x32 API always sets bit 30. 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__i386__) || defined(__x86_64__) 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *invalidX32 = 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_RET+BPF_K, 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Kill("Illegal mixing of system call ABIs").err_); 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *checkX32 = 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__x86_64__) && defined(__ILP32__) 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, invalidX32); 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, invalidX32, 0); 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(tail, checkX32); 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tail = checkX32; 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append jump table to our pre-amble 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gen->JoinInstructions(tail, jumptable); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Turn the DAG into a vector of instructions. 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Program *program = new Program(); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gen->Compile(head, program); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete gen; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure compilation resulted in BPF program that executes 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correctly. Otherwise, there is an internal error in our BPF compiler. 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is really nothing the caller can do until the bug is fixed. 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (force_verification) { 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verification is expensive. We only perform this step, if we are 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // compiled in debug mode, or if the caller explicitly requested 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // verification. 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VerifyProgram(*program, has_unsafe_traps); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return program; 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Sandbox::VerifyProgram(const Program& program, bool has_unsafe_traps) { 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we previously rewrote the BPF program so that it calls user-space 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // whenever we return an "errno" value from the filter, then we have to 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // wrap our system call evaluator to perform the same operation. Otherwise, 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the verifier would also report a mismatch in return codes. 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Evaluators redirected_evaluators; 6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) redirected_evaluators.push_back( 6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::make_pair(RedirectToUserspaceEvalWrapper, evaluators_)); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *err = NULL; 6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!Verifier::VerifyBPF( 6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) program, 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) has_unsafe_traps ? redirected_evaluators : *evaluators_, 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &err)) { 7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CodeGen::PrintProgram(program); 7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE(err); 7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Sandbox::FindRanges(Ranges *ranges) { 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Please note that "struct seccomp_data" defines system calls as a signed 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // int32_t, but BPF instructions always operate on unsigned quantities. We 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deal with this disparity by enumerating from MIN_SYSCALL to MAX_SYSCALL, 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then verifying that the rest of the number range (both positive and 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // negative) all return the same ErrorCode. 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EvaluateSyscall evaluate_syscall = evaluators_->begin()->first; 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void *aux = evaluators_->begin()->second; 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t old_sysnum = 0; 7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorCode old_err = evaluate_syscall(this, old_sysnum, aux); 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorCode invalid_err = evaluate_syscall(this, MIN_SYSCALL - 1, 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aux); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SyscallIterator iter(false); !iter.Done(); ) { 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t sysnum = iter.Next(); 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorCode err = evaluate_syscall(this, static_cast<int>(sysnum), aux); 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!iter.IsValid(sysnum) && !invalid_err.Equals(err)) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A proper sandbox policy should always treat system calls outside of 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the range MIN_SYSCALL..MAX_SYSCALL (i.e. anything that returns 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "false" for SyscallIterator::IsValid()) identically. Typically, all 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of these system calls would be denied with the same ErrorCode. 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Invalid seccomp policy"); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!err.Equals(old_err) || iter.Done()) { 7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ranges->push_back(Range(old_sysnum, sysnum - 1, old_err)); 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_sysnum = sysnum; 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_err = err; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Instruction *Sandbox::AssembleJumpTable(CodeGen *gen, 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ranges::const_iterator start, 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ranges::const_iterator stop) { 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We convert the list of system call ranges into jump table that performs 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a binary search over the ranges. 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As a sanity check, we need to have at least one distinct ranges for us 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to be able to build a jump table. 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stop - start <= 0) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANDBOX_DIE("Invalid set of system call ranges"); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (stop - start == 1) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have narrowed things down to a single range object, we can 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return from the BPF filter program. 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return RetExpression(gen, start->err); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pick the range object that is located at the mid point of our list. 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We compare our system call number against the lowest valid system call 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number in this range object. If our number is lower, it is outside of 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this range object. If it is greater or equal, it might be inside. 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ranges::const_iterator mid = start + (stop - start)/2; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sub-divide the list of ranges and continue recursively. 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *jf = AssembleJumpTable(gen, start, mid); 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *jt = AssembleJumpTable(gen, mid, stop); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gen->MakeInstruction(BPF_JMP+BPF_JGE+BPF_K, mid->from, jt, jf); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Instruction *Sandbox::RetExpression(CodeGen *gen, const ErrorCode& err) { 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (err.error_type_ == ErrorCode::ET_COND) { 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CondExpression(gen, err); 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gen->MakeInstruction(BPF_RET+BPF_K, err); 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Instruction *Sandbox::CondExpression(CodeGen *gen, const ErrorCode& cond) { 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We can only inspect the six system call arguments that are passed in 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CPU registers. 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cond.argno_ < 0 || cond.argno_ >= 6) { 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("Internal compiler error; invalid argument number " 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "encountered"); 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // BPF programs operate on 32bit entities. Load both halfs of the 64bit 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // system call argument and then generate suitable conditional statements. 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *msb_head = 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_LD+BPF_W+BPF_ABS, 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SECCOMP_ARG_MSB_IDX(cond.argno_)); 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *msb_tail = msb_head; 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *lsb_head = 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_LD+BPF_W+BPF_ABS, 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SECCOMP_ARG_LSB_IDX(cond.argno_)); 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *lsb_tail = lsb_head; 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Emit a suitable comparison statement. 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (cond.op_) { 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ErrorCode::OP_EQUAL: 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Compare the least significant bits for equality 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_tail = gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<uint32_t>(cond.value_), 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.passed_), 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.failed_)); 7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(lsb_head, lsb_tail); 8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we are looking at a 64bit argument, we need to also compare the 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // most significant bits. 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cond.width_ == ErrorCode::TP_64BIT) { 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_tail = gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<uint32_t>(cond.value_ >> 32), 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head, 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.failed_)); 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(msb_head, msb_tail); 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ErrorCode::OP_HAS_ALL_BITS: 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check the bits in the LSB half of the system call argument. Our 8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OP_HAS_ALL_BITS operator passes, iff all of the bits are set. This is 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // different from the kernel's BPF_JSET operation which passes, if any of 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the bits are set. 8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Of course, if there is only a single set bit (or none at all), then 8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // things get easier. 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t lsb_bits = static_cast<uint32_t>(cond.value_); 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int lsb_bit_count = popcount(lsb_bits); 8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (lsb_bit_count == 0) { 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No bits are set in the LSB half. The test will always pass. 8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head = RetExpression(gen, *cond.passed_); 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_tail = NULL; 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (lsb_bit_count == 1) { 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Exactly one bit is set in the LSB half. We can use the BPF_JSET 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // operator. 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_bits, 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.passed_), 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.failed_)); 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(lsb_head, lsb_tail); 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // More than one bit is set in the LSB half. We need to combine 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // BPF_AND and BPF_JEQ to test whether all of these bits are in fact 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // set in the system call argument. 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(lsb_head, 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_ALU+BPF_AND+BPF_K, 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_bits, 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_tail = gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_bits, 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.passed_), 8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.failed_)))); 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we are looking at a 64bit argument, we need to also check the bits 8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in the MSB half of the system call argument. 8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cond.width_ == ErrorCode::TP_64BIT) { 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t msb_bits = static_cast<uint32_t>(cond.value_ >> 32); 8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int msb_bit_count = popcount(msb_bits); 8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (msb_bit_count == 0) { 8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No bits are set in the MSB half. The test will always pass. 8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_head = lsb_head; 8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (msb_bit_count == 1) { 8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Exactly one bit is set in the MSB half. We can use the BPF_JSET 8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // operator. 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_bits, 8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head, 8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.failed_)); 8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(msb_head, msb_tail); 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // More than one bit is set in the MSB half. We need to combine 8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // BPF_AND and BPF_JEQ to test whether all of these bits are in fact 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // set in the system call argument. 8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(msb_head, 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_ALU+BPF_AND+BPF_K, 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_bits, 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_bits, 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head, 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.failed_)))); 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ErrorCode::OP_HAS_ANY_BITS: 8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check the bits in the LSB half of the system call argument. Our 8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // OP_HAS_ANY_BITS operator passes, iff any of the bits are set. This maps 8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // nicely to the kernel's BPF_JSET operation. 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t lsb_bits = static_cast<uint32_t>(cond.value_); 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!lsb_bits) { 8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No bits are set in the LSB half. The test will always fail. 8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head = RetExpression(gen, *cond.failed_); 8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_tail = NULL; 8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_bits, 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.passed_), 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.failed_)); 8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(lsb_head, lsb_tail); 8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we are looking at a 64bit argument, we need to also check the bits 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in the MSB half of the system call argument. 8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cond.width_ == ErrorCode::TP_64BIT) { 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t msb_bits = static_cast<uint32_t>(cond.value_ >> 32); 9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!msb_bits) { 9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No bits are set in the MSB half. The test will always fail. 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_head = lsb_head; 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, 9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_bits, 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetExpression(gen, *cond.passed_), 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head); 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions(msb_head, msb_tail); 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(markus): Need to add support for OP_GREATER 9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("Not implemented"); 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ensure that we never pass a 64bit value, when we only expect a 32bit 9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // value. This is somewhat complicated by the fact that on 64bit systems, 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // callers could legitimately pass in a non-zero value in the MSB, iff the 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // LSB has been sign-extended into the MSB. 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cond.width_ == ErrorCode::TP_32BIT) { 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (cond.value_ >> 32) { 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SANDBOX_DIE("Invalid comparison of a 32bit system call argument " 9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "against a 64bit constant; this test is always false."); 9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Instruction *invalid_64bit = RetExpression(gen, Unexpected64bitArgument()); 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) #if __SIZEOF_POINTER__ > 4 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) invalid_64bit = 9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 0xFFFFFFFF, 9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_LD+BPF_W+BPF_ABS, 9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SECCOMP_ARG_LSB_IDX(cond.argno_), 9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JGE+BPF_K, 0x80000000, 9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head, 9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) invalid_64bit)), 9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) invalid_64bit); 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) #endif 9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->JoinInstructions( 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msb_tail, 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 0, 9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lsb_head, 9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) invalid_64bit)); 9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return msb_head; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode Sandbox::Unexpected64bitArgument() { 9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Kill("Unexpected 64bit argument detected"); 9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode Sandbox::Trap(Trap::TrapFnc fnc, const void *aux) { 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Trap::MakeTrap(fnc, aux, true /* Safe Trap */); 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode Sandbox::UnsafeTrap(Trap::TrapFnc fnc, const void *aux) { 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Trap::MakeTrap(fnc, aux, false /* Unsafe Trap */); 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)intptr_t Sandbox::ForwardSyscall(const struct arch_seccomp_data& args) { 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SandboxSyscall(args.nr, 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<intptr_t>(args.args[0]), 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<intptr_t>(args.args[1]), 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<intptr_t>(args.args[2]), 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<intptr_t>(args.args[3]), 9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<intptr_t>(args.args[4]), 9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<intptr_t>(args.args[5])); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ErrorCode Sandbox::Cond(int argno, ErrorCode::ArgType width, 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ErrorCode::Operation op, uint64_t value, 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ErrorCode& passed, const ErrorCode& failed) { 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ErrorCode(argno, width, op, value, 9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &*conds_->insert(passed).first, 9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &*conds_->insert(failed).first); 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ErrorCode Sandbox::Kill(const char *msg) { 9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Trap(BpfFailure, const_cast<char *>(msg)); 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 986