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