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/nacl_sandbox_linux.h" 6 7 #include <errno.h> 8 #include <signal.h> 9 #include <sys/ptrace.h> 10 11 #include "base/basictypes.h" 12 #include "base/callback.h" 13 #include "base/compiler_specific.h" 14 #include "base/logging.h" 15 #include "build/build_config.h" 16 #include "content/public/common/sandbox_init.h" 17 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 18 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" 19 #include "sandbox/linux/services/linux_syscalls.h" 20 21 using sandbox::ErrorCode; 22 using sandbox::SandboxBPF; 23 using sandbox::SandboxBPFPolicy; 24 25 namespace { 26 27 // On ARM and x86_64, System V shared memory calls have each their own system 28 // call, while on i386 they are multiplexed. 29 #if defined(__x86_64__) || defined(__arm__) 30 bool IsSystemVSharedMemory(int sysno) { 31 switch (sysno) { 32 case __NR_shmat: 33 case __NR_shmctl: 34 case __NR_shmdt: 35 case __NR_shmget: 36 return true; 37 default: 38 return false; 39 } 40 } 41 #endif 42 43 #if defined(__i386__) 44 // Big system V multiplexing system call. 45 bool IsSystemVIpc(int sysno) { 46 switch (sysno) { 47 case __NR_ipc: 48 return true; 49 default: 50 return false; 51 } 52 } 53 #endif 54 55 class NaClBPFSandboxPolicy : public SandboxBPFPolicy { 56 public: 57 NaClBPFSandboxPolicy() 58 : baseline_policy_(content::GetBPFSandboxBaselinePolicy()) {} 59 virtual ~NaClBPFSandboxPolicy() {} 60 61 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, 62 int system_call_number) const OVERRIDE; 63 64 private: 65 scoped_ptr<SandboxBPFPolicy> baseline_policy_; 66 DISALLOW_COPY_AND_ASSIGN(NaClBPFSandboxPolicy); 67 }; 68 69 ErrorCode NaClBPFSandboxPolicy::EvaluateSyscall( 70 sandbox::SandboxBPF* sb, int sysno) const { 71 DCHECK(baseline_policy_); 72 switch (sysno) { 73 // TODO(jln): NaCl's GDB debug stub uses the following socket system calls, 74 // see if it can be restricted a bit. 75 #if defined(__x86_64__) || defined(__arm__) 76 // transport_common.cc needs this. 77 case __NR_accept: 78 case __NR_setsockopt: 79 #elif defined(__i386__) 80 case __NR_socketcall: 81 #endif 82 // trusted/service_runtime/linux/thread_suspension.c needs sigwait() and is 83 // used by NaCl's GDB debug stub. 84 case __NR_rt_sigtimedwait: 85 #if defined(__i386__) 86 // Needed on i386 to set-up the custom segments. 87 case __NR_modify_ldt: 88 #endif 89 // NaClAddrSpaceBeforeAlloc needs prlimit64. 90 case __NR_prlimit64: 91 // NaCl uses custom signal stacks. 92 case __NR_sigaltstack: 93 // Below is fairly similar to the policy for a Chromium renderer. 94 // TODO(jln): restrict clone(), ioctl() and prctl(). 95 case __NR_ioctl: 96 #if defined(__i386__) || defined(__x86_64__) 97 case __NR_getrlimit: 98 #endif 99 #if defined(__i386__) || defined(__arm__) 100 case __NR_ugetrlimit: 101 #endif 102 // NaCl runtime exposes clock_getres to untrusted code. 103 case __NR_clock_getres: 104 // NaCl runtime uses flock to simulate POSIX behavior for pwrite. 105 case __NR_flock: 106 case __NR_pread64: 107 case __NR_pwrite64: 108 case __NR_sched_get_priority_max: 109 case __NR_sched_get_priority_min: 110 case __NR_sched_getaffinity: 111 case __NR_sched_getparam: 112 case __NR_sched_getscheduler: 113 case __NR_sched_setscheduler: 114 case __NR_setpriority: 115 case __NR_sysinfo: 116 // __NR_times needed as clock() is called by CommandBufferHelper, which is 117 // used by NaCl applications that use Pepper's 3D interfaces. 118 // See crbug.com/264856 for details. 119 case __NR_times: 120 case __NR_uname: 121 return ErrorCode(ErrorCode::ERR_ALLOWED); 122 case __NR_ptrace: 123 return ErrorCode(EPERM); 124 default: 125 // TODO(jln): look into getting rid of System V shared memory: 126 // platform_qualify/linux/sysv_shm_and_mmap.c makes it a requirement, but 127 // it may not be needed in all cases. Chromium renderers don't need 128 // System V shared memory on Aura. 129 #if defined(__x86_64__) || defined(__arm__) 130 if (IsSystemVSharedMemory(sysno)) 131 return ErrorCode(ErrorCode::ERR_ALLOWED); 132 #elif defined(__i386__) 133 if (IsSystemVIpc(sysno)) 134 return ErrorCode(ErrorCode::ERR_ALLOWED); 135 #endif 136 return baseline_policy_->EvaluateSyscall(sb, sysno); 137 } 138 NOTREACHED(); 139 // GCC wants this. 140 return ErrorCode(EPERM); 141 } 142 143 void RunSandboxSanityChecks() { 144 errno = 0; 145 // Make a ptrace request with an invalid PID. 146 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); 147 CHECK_EQ(-1, ptrace_ret); 148 // Without the sandbox on, this ptrace call would ESRCH instead. 149 CHECK_EQ(EPERM, errno); 150 } 151 152 } // namespace 153 154 bool InitializeBPFSandbox() { 155 bool sandbox_is_initialized = content::InitializeSandbox( 156 scoped_ptr<SandboxBPFPolicy>(new NaClBPFSandboxPolicy())); 157 if (sandbox_is_initialized) { 158 RunSandboxSanityChecks(); 159 return true; 160 } 161 return false; 162 } 163