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 |