| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 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 "chrome/nacl/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 inline bool IsPlatformX86() { | |
| 24 #if defined(__x86_64__) || defined(__i386__) | |
| 25 return true; | |
| 26 #else | |
| 27 return false; | |
| 28 #endif | |
| 29 } | |
| 30 | |
| 31 // On ARM and x86_64, System V shared memory calls have each their own system | |
| 32 // call, while on i386 they are multiplexed. | |
| 33 #if defined(__x86_64__) || defined(__arm__) | |
| 34 bool IsSystemVSharedMemory(int sysno) { | |
| 35 switch (sysno) { | |
| 36 case __NR_shmat: | |
| 37 case __NR_shmctl: | |
| 38 case __NR_shmdt: | |
| 39 case __NR_shmget: | |
| 40 return true; | |
| 41 default: | |
| 42 return false; | |
| 43 } | |
| 44 } | |
| 45 #endif | |
| 46 | |
| 47 #if defined(__i386__) | |
| 48 // Big system V multiplexing system call. | |
| 49 bool IsSystemVIpc(int sysno) { | |
| 50 switch (sysno) { | |
| 51 case __NR_ipc: | |
| 52 return true; | |
| 53 default: | |
| 54 return false; | |
| 55 } | |
| 56 } | |
| 57 #endif | |
| 58 | |
| 59 ErrorCode NaClBpfSandboxPolicy( | |
| 60 playground2::Sandbox* sb, int sysno, void* aux) { | |
| 61 const playground2::BpfSandboxPolicyCallback baseline_policy = | |
| 62 content::GetBpfSandboxBaselinePolicy(); | |
| 63 switch (sysno) { | |
| 64 // TODO(jln): NaCl's GDB debug stub uses the following socket system calls, | |
| 65 // see if it can be restricted a bit. | |
| 66 #if defined(__x86_64__) || defined(__arm__) | |
| 67 // transport_common.cc needs this. | |
| 68 case __NR_accept: | |
| 69 case __NR_setsockopt: | |
| 70 #elif defined(__i386__) | |
| 71 case __NR_socketcall: | |
| 72 #endif | |
| 73 // trusted/service_runtime/linux/thread_suspension.c needs sigwait() and is | |
| 74 // used by NaCl's GDB debug stub. | |
| 75 case __NR_rt_sigtimedwait: | |
| 76 #if defined(__i386__) | |
| 77 // Needed on i386 to set-up the custom segments. | |
| 78 case __NR_modify_ldt: | |
| 79 #endif | |
| 80 // NaClAddrSpaceBeforeAlloc needs prlimit64. | |
| 81 case __NR_prlimit64: | |
| 82 // NaCl uses custom signal stacks. | |
| 83 case __NR_sigaltstack: | |
| 84 // Below is fairly similar to the policy for a Chromium renderer. | |
| 85 // TODO(jln): restrict clone(), ioctl() and prctl(). | |
| 86 case __NR_ioctl: | |
| 87 #if defined(__i386__) || defined(__x86_64__) | |
| 88 case __NR_getrlimit: | |
| 89 #endif | |
| 90 #if defined(__i386__) || defined(__arm__) | |
| 91 case __NR_ugetrlimit: | |
| 92 #endif | |
| 93 case __NR_pread64: | |
| 94 case __NR_pwrite64: | |
| 95 case __NR_sched_get_priority_max: | |
| 96 case __NR_sched_get_priority_min: | |
| 97 case __NR_sched_getaffinity: | |
| 98 case __NR_sched_getparam: | |
| 99 case __NR_sched_getscheduler: | |
| 100 case __NR_sched_setscheduler: | |
| 101 case __NR_setpriority: | |
| 102 case __NR_sysinfo: | |
| 103 case __NR_uname: | |
| 104 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
| 105 case __NR_ptrace: | |
| 106 return ErrorCode(EPERM); | |
| 107 default: | |
| 108 // TODO(jln): look into getting rid of System V shared memory: | |
| 109 // platform_qualify/linux/sysv_shm_and_mmap.c makes it a requirement, but | |
| 110 // it may not be needed in all cases. Chromium renderers don't need | |
| 111 // System V shared memory on Aura. | |
| 112 #if defined(__x86_64__) || defined(__arm__) | |
| 113 if (IsSystemVSharedMemory(sysno)) | |
| 114 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
| 115 #elif defined(__i386__) | |
| 116 if (IsSystemVIpc(sysno)) | |
| 117 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
| 118 #endif | |
| 119 return baseline_policy.Run(sb, sysno, aux); | |
| 120 } | |
| 121 NOTREACHED(); | |
| 122 // GCC wants this. | |
| 123 return ErrorCode(EPERM); | |
| 124 } | |
| 125 | |
| 126 void RunSandboxSanityChecks() { | |
| 127 errno = 0; | |
| 128 // Make a ptrace request with an invalid PID. | |
| 129 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); | |
| 130 CHECK_EQ(-1, ptrace_ret); | |
| 131 // Without the sandbox on, this ptrace call would ESRCH instead. | |
| 132 CHECK_EQ(EPERM, errno); | |
| 133 } | |
| 134 | |
| 135 } // namespace | |
| 136 | |
| 137 bool InitializeBpfSandbox() { | |
| 138 // TODO(jln): enable the sandbox on ARM as well. | |
| 139 if (!IsPlatformX86()) | |
| 140 return false; | |
| 141 bool sandbox_is_initialized = | |
| 142 content::InitializeSandbox(NaClBpfSandboxPolicy); | |
| 143 if (sandbox_is_initialized) { | |
| 144 RunSandboxSanityChecks(); | |
| 145 // TODO(jln): Find a way to fix this. | |
| 146 // The sandbox' SIGSYS handler trips NaCl, so we disable it. | |
| 147 // If SIGSYS is triggered it'll now execute the default action | |
| 148 // (CORE). This will make it hard to track down bugs and sandbox violations. | |
| 149 CHECK(signal(SIGSYS, SIG_DFL) != SIG_ERR); | |
| 150 return true; | |
| 151 } | |
| 152 return false; | |
| 153 } | |
| OLD | NEW |