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 <signal.h> 8 #include <sys/ptrace.h> 9 10 #include "base/callback.h" 11 #include "base/compiler_specific.h" 12 #include "base/logging.h" 13 #include "build/build_config.h" 14 #include "content/public/common/sandbox_init.h" 15 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 16 #include "sandbox/linux/services/linux_syscalls.h" 17 18 using playground2::ErrorCode; 19 using playground2::Sandbox; 20 21 namespace { 22 23 // On ARM and x86_64, System V shared memory calls have each their own system 24 // call, while on i386 they are multiplexed. 25 #if defined(__x86_64__) || defined(__arm__) 26 bool IsSystemVSharedMemory(int sysno) { 27 switch (sysno) { 28 case __NR_shmat: 29 case __NR_shmctl: 30 case __NR_shmdt: 31 case __NR_shmget: 32 return true; 33 default: 34 return false; 35 } 36 } 37 #endif 38 39 #if defined(__i386__) 40 // Big system V multiplexing system call. 41 bool IsSystemVIpc(int sysno) { 42 switch (sysno) { 43 case __NR_ipc: 44 return true; 45 default: 46 return false; 47 } 48 } 49 #endif 50 51 ErrorCode NaClBpfSandboxPolicy( 52 playground2::Sandbox* sb, int sysno, void* aux) { 53 const playground2::BpfSandboxPolicyCallback baseline_policy = 54 content::GetBpfSandboxBaselinePolicy(); 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__) 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__) 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 // TODO(jln): restrict clone(), ioctl() and prctl(). 78 case __NR_ioctl: 79 #if defined(__i386__) || defined(__x86_64__) 80 case __NR_getrlimit: 81 #endif 82 #if defined(__i386__) || defined(__arm__) 83 case __NR_ugetrlimit: 84 #endif 85 // NaCl runtime exposes clock_getres to untrusted code. 86 case __NR_clock_getres: 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_setpriority: 96 case __NR_sysinfo: 97 // __NR_times needed as clock() is called by CommandBufferHelper, which is 98 // used by NaCl applications that use Pepper's 3D interfaces. 99 // See crbug.com/264856 for details. 100 case __NR_times: 101 case __NR_uname: 102 return ErrorCode(ErrorCode::ERR_ALLOWED); 103 case __NR_ptrace: 104 return ErrorCode(EPERM); 105 default: 106 // TODO(jln): look into getting rid of System V shared memory: 107 // platform_qualify/linux/sysv_shm_and_mmap.c makes it a requirement, but 108 // it may not be needed in all cases. Chromium renderers don't need 109 // System V shared memory on Aura. 110 #if defined(__x86_64__) || defined(__arm__) 111 if (IsSystemVSharedMemory(sysno)) 112 return ErrorCode(ErrorCode::ERR_ALLOWED); 113 #elif defined(__i386__) 114 if (IsSystemVIpc(sysno)) 115 return ErrorCode(ErrorCode::ERR_ALLOWED); 116 #endif 117 return baseline_policy.Run(sb, sysno, aux); 118 } 119 NOTREACHED(); 120 // GCC wants this. 121 return ErrorCode(EPERM); 122 } 123 124 void RunSandboxSanityChecks() { 125 errno = 0; 126 // Make a ptrace request with an invalid PID. 127 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); 128 CHECK_EQ(-1, ptrace_ret); 129 // Without the sandbox on, this ptrace call would ESRCH instead. 130 CHECK_EQ(EPERM, errno); 131 } 132 133 } // namespace 134 135 bool InitializeBpfSandbox() { 136 bool sandbox_is_initialized = 137 content::InitializeSandbox(NaClBpfSandboxPolicy); 138 if (sandbox_is_initialized) { 139 RunSandboxSanityChecks(); 140 return true; 141 } 142 return false; 143 } 144