1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.h" 6 7 #include "build/build_config.h" 8 9 #if defined(USE_SECCOMP_BPF) 10 11 #include <errno.h> 12 #include <signal.h> 13 #include <sys/ptrace.h> 14 15 #include "base/basictypes.h" 16 #include "base/callback.h" 17 #include "base/compiler_specific.h" 18 #include "base/logging.h" 19 20 #include "content/public/common/sandbox_init.h" 21 #include "sandbox/linux/bpf_dsl/bpf_dsl.h" 22 #include "sandbox/linux/services/linux_syscalls.h" 23 24 #endif // defined(USE_SECCOMP_BPF) 25 26 namespace nacl { 27 28 #if defined(USE_SECCOMP_BPF) 29 30 namespace { 31 32 using sandbox::bpf_dsl::Allow; 33 using sandbox::bpf_dsl::Error; 34 using sandbox::bpf_dsl::ResultExpr; 35 36 class NaClBPFSandboxPolicy : public sandbox::bpf_dsl::SandboxBPFDSLPolicy { 37 public: 38 NaClBPFSandboxPolicy() 39 : baseline_policy_(content::GetBPFSandboxBaselinePolicy()) {} 40 virtual ~NaClBPFSandboxPolicy() {} 41 42 virtual ResultExpr EvaluateSyscall(int system_call_number) const OVERRIDE; 43 virtual ResultExpr InvalidSyscall() const OVERRIDE { 44 return baseline_policy_->InvalidSyscall(); 45 } 46 47 private: 48 scoped_ptr<sandbox::bpf_dsl::SandboxBPFDSLPolicy> baseline_policy_; 49 50 DISALLOW_COPY_AND_ASSIGN(NaClBPFSandboxPolicy); 51 }; 52 53 ResultExpr NaClBPFSandboxPolicy::EvaluateSyscall(int sysno) const { 54 DCHECK(baseline_policy_); 55 switch (sysno) { 56 // TODO(jln): NaCl's GDB debug stub uses the following socket system calls, 57 // see if it can be restricted a bit. 58 #if defined(__x86_64__) || defined(__arm__) || defined(__mips__) 59 // transport_common.cc needs this. 60 case __NR_accept: 61 case __NR_setsockopt: 62 #elif defined(__i386__) 63 case __NR_socketcall: 64 #endif 65 // trusted/service_runtime/linux/thread_suspension.c needs sigwait() and is 66 // used by NaCl's GDB debug stub. 67 case __NR_rt_sigtimedwait: 68 #if defined(__i386__) || defined(__mips__) 69 // Needed on i386 to set-up the custom segments. 70 case __NR_modify_ldt: 71 #endif 72 // NaClAddrSpaceBeforeAlloc needs prlimit64. 73 case __NR_prlimit64: 74 // NaCl uses custom signal stacks. 75 case __NR_sigaltstack: 76 // Below is fairly similar to the policy for a Chromium renderer. 77 #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) 78 case __NR_getrlimit: 79 #endif 80 #if defined(__i386__) || defined(__arm__) 81 case __NR_ugetrlimit: 82 #endif 83 // NaCl runtime exposes clock_getres to untrusted code. 84 case __NR_clock_getres: 85 // NaCl runtime uses flock to simulate POSIX behavior for pwrite. 86 case __NR_flock: 87 case __NR_pread64: 88 case __NR_pwrite64: 89 case __NR_sched_get_priority_max: 90 case __NR_sched_get_priority_min: 91 case __NR_sched_getaffinity: 92 case __NR_sched_getparam: 93 case __NR_sched_getscheduler: 94 case __NR_sched_setscheduler: 95 case __NR_sysinfo: 96 // __NR_times needed as clock() is called by CommandBufferHelper, which is 97 // used by NaCl applications that use Pepper's 3D interfaces. 98 // See crbug.com/264856 for details. 99 case __NR_times: 100 case __NR_uname: 101 return Allow(); 102 case __NR_ioctl: 103 case __NR_ptrace: 104 return Error(EPERM); 105 default: 106 return baseline_policy_->EvaluateSyscall(sysno); 107 } 108 NOTREACHED(); 109 // GCC wants this. 110 return Error(EPERM); 111 } 112 113 void RunSandboxSanityChecks() { 114 errno = 0; 115 // Make a ptrace request with an invalid PID. 116 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); 117 CHECK_EQ(-1, ptrace_ret); 118 // Without the sandbox on, this ptrace call would ESRCH instead. 119 CHECK_EQ(EPERM, errno); 120 } 121 122 } // namespace 123 124 #else 125 126 #error "Seccomp-bpf disabled on supported architecture!" 127 128 #endif // defined(USE_SECCOMP_BPF) 129 130 bool InitializeBPFSandbox() { 131 #if defined(USE_SECCOMP_BPF) 132 bool sandbox_is_initialized = content::InitializeSandbox( 133 scoped_ptr<sandbox::bpf_dsl::SandboxBPFDSLPolicy>( 134 new NaClBPFSandboxPolicy)); 135 if (sandbox_is_initialized) { 136 RunSandboxSanityChecks(); 137 return true; 138 } 139 #endif // defined(USE_SECCOMP_BPF) 140 return false; 141 } 142 143 } // namespace nacl 144