OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/nacl/loader/nacl_sandbox_linux.h" | 5 #include "components/nacl/loader/nacl_sandbox_linux.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <linux/net.h> | |
8 #include <signal.h> | 9 #include <signal.h> |
9 #include <sys/ptrace.h> | 10 #include <sys/ptrace.h> |
11 #include <sys/syscall.h> | |
10 | 12 |
11 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
12 #include "base/callback.h" | 14 #include "base/callback.h" |
13 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
14 #include "base/logging.h" | 16 #include "base/logging.h" |
15 #include "build/build_config.h" | 17 #include "build/build_config.h" |
16 | 18 |
17 #if defined(USE_SECCOMP_BPF) | 19 #if defined(USE_SECCOMP_BPF) |
18 #include "content/public/common/sandbox_init.h" | 20 #include "content/public/common/sandbox_init.h" |
21 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" | |
22 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" | |
19 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 23 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
20 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" | 24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" |
25 #include "sandbox/linux/seccomp-bpf/trap.h" | |
21 #include "sandbox/linux/services/linux_syscalls.h" | 26 #include "sandbox/linux/services/linux_syscalls.h" |
22 | 27 |
23 using sandbox::ErrorCode; | 28 using sandbox::ErrorCode; |
24 using sandbox::SandboxBPF; | 29 using sandbox::SandboxBPF; |
25 using sandbox::SandboxBPFPolicy; | 30 using sandbox::SandboxBPFPolicy; |
26 | 31 |
27 namespace { | 32 namespace { |
28 | 33 |
29 // On ARM and x86_64, System V shared memory calls have each their own system | 34 // On ARM and x86_64, System V shared memory calls have each their own system |
30 // call, while on i386 they are multiplexed. | 35 // call, while on i386 they are multiplexed. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 case __NR_sched_setscheduler: | 120 case __NR_sched_setscheduler: |
116 case __NR_setpriority: | 121 case __NR_setpriority: |
117 case __NR_sysinfo: | 122 case __NR_sysinfo: |
118 // __NR_times needed as clock() is called by CommandBufferHelper, which is | 123 // __NR_times needed as clock() is called by CommandBufferHelper, which is |
119 // used by NaCl applications that use Pepper's 3D interfaces. | 124 // used by NaCl applications that use Pepper's 3D interfaces. |
120 // See crbug.com/264856 for details. | 125 // See crbug.com/264856 for details. |
121 case __NR_times: | 126 case __NR_times: |
122 case __NR_uname: | 127 case __NR_uname: |
123 return ErrorCode(ErrorCode::ERR_ALLOWED); | 128 return ErrorCode(ErrorCode::ERR_ALLOWED); |
124 case __NR_ptrace: | 129 case __NR_ptrace: |
130 // For RunSandboxSanityChecks(). | |
125 return ErrorCode(EPERM); | 131 return ErrorCode(EPERM); |
126 default: | 132 default: |
127 // TODO(jln): look into getting rid of System V shared memory: | 133 // 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 | 134 // 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 | 135 // it may not be needed in all cases. Chromium renderers don't need |
130 // System V shared memory on Aura. | 136 // System V shared memory on Aura. |
131 #if defined(__x86_64__) || defined(__arm__) | 137 #if defined(__x86_64__) || defined(__arm__) |
132 if (IsSystemVSharedMemory(sysno)) | 138 if (IsSystemVSharedMemory(sysno)) |
133 return ErrorCode(ErrorCode::ERR_ALLOWED); | 139 return ErrorCode(ErrorCode::ERR_ALLOWED); |
134 #elif defined(__i386__) | 140 #elif defined(__i386__) |
135 if (IsSystemVIpc(sysno)) | 141 if (IsSystemVIpc(sysno)) |
136 return ErrorCode(ErrorCode::ERR_ALLOWED); | 142 return ErrorCode(ErrorCode::ERR_ALLOWED); |
137 #endif | 143 #endif |
138 return baseline_policy_->EvaluateSyscall(sb, sysno); | 144 return baseline_policy_->EvaluateSyscall(sb, sysno); |
139 } | 145 } |
140 NOTREACHED(); | 146 NOTREACHED(); |
141 // GCC wants this. | 147 // GCC wants this. |
142 return ErrorCode(EPERM); | 148 return ErrorCode(EPERM); |
143 } | 149 } |
144 | 150 |
151 // The seccomp sandbox policy for NaCl non-SFI mode. Note that this | |
152 // policy must be as strong as possible, as non-SFI mode heavily | |
153 // depends on seccomp sandbox. | |
154 class NonSfiNaClBPFSandboxPolicy : public SandboxBPFPolicy { | |
155 public: | |
156 explicit NonSfiNaClBPFSandboxPolicy() | |
157 : baseline_policy_(content::GetBPFSandboxBaselinePolicy()) { | |
158 } | |
159 virtual ~NonSfiNaClBPFSandboxPolicy() {} | |
160 | |
161 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, | |
162 int system_call_number) const OVERRIDE; | |
163 | |
164 private: | |
165 scoped_ptr<SandboxBPFPolicy> baseline_policy_; | |
166 DISALLOW_COPY_AND_ASSIGN(NonSfiNaClBPFSandboxPolicy); | |
167 }; | |
168 | |
169 ErrorCode NonSfiNaClBPFSandboxPolicy::EvaluateSyscall( | |
170 sandbox::SandboxBPF* sb, int sysno) const { | |
171 DCHECK(baseline_policy_); | |
172 ErrorCode ret = baseline_policy_->EvaluateSyscall(sb, sysno); | |
Mark Seaborn
2014/03/18 23:53:58
You're falling through to the baseline policy. I
jln (very slow on Chromium)
2014/03/20 00:54:53
I absolutely agree with Mark here. We need a short
hamaji
2014/03/24 15:56:37
Done. I also stopped using sandbox::Restrict* as t
| |
173 switch (sysno) { | |
174 // __NR_times needed as clock() is called by CommandBufferHelper, which is | |
175 // used by NaCl applications that use Pepper's 3D interfaces. | |
176 // See crbug.com/264856 for details. | |
177 case __NR_times: | |
178 ret = ErrorCode(ErrorCode::ERR_ALLOWED); | |
179 break; | |
180 | |
181 // Conditionally allowed syscalls: | |
182 case __NR_clone: { | |
183 // We allow clone only for new thread creation. | |
184 ret = sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
185 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | | |
186 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | | |
187 CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID, | |
188 ErrorCode(ErrorCode::ERR_ALLOWED), | |
189 sb->Trap(sandbox::SIGSYSCloneFailure, NULL)); | |
190 break; | |
191 } | |
192 case __NR_prctl: | |
193 // We only allow PR_SET_NAME, PR_SET_DUMPABLE, and PR_GET_DUMPABLE. | |
Mark Seaborn
2014/03/18 23:53:58
I don't think these are operations that should be
hamaji
2014/03/24 15:56:37
I stopped using RestrictPrctl. Now it returns EPER
| |
194 ret = sandbox::RestrictPrctl(sb); | |
195 break; | |
196 #if defined(__i686__) | |
Mark Seaborn
2014/03/18 23:53:58
__i386__ would be preferred.
hamaji
2014/03/24 15:56:37
Done.
| |
197 case __NR_socketcall: { | |
198 // We only allow socketpair, sendmsg, and recvmsg. | |
199 ret = sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
200 SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED), | |
201 sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
202 SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED), | |
203 sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
204 SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED), | |
205 ErrorCode(EPERM)))); | |
206 break; | |
207 } | |
208 #endif | |
209 | |
210 // It is allowed to call the following syscalls, but they just | |
211 // return EPERM. | |
212 case __NR_ptrace: | |
213 // For RunSandboxSanityChecks(). | |
214 ret = ErrorCode(EPERM); | |
215 break; | |
216 case __NR_set_robust_list: | |
217 // glibc uses this for its pthread implementation. If we return | |
218 // EPERM for this, glibc will stop using this. | |
219 // TODO(hamaji): newlib does not use this. Make this SIGTRAP once | |
220 // we have switched to newlib. | |
221 ret = ErrorCode(EPERM); | |
222 break; | |
223 #if !defined(__x86_64__) | |
224 case __NR_getegid32: | |
225 case __NR_geteuid32: | |
226 case __NR_getgid32: | |
227 case __NR_getuid32: | |
228 #endif | |
229 // third_party/libevent uses them, but we can just return -1 from | |
230 // them as it is just checking getuid() != geteuid() and | |
231 // getgid() != getegid() | |
232 ret = ErrorCode(EPERM); | |
233 break; | |
234 #if !defined(__arm__) | |
Mark Seaborn
2014/03/18 23:53:58
Should be "defined(__i386__) || defined(__x86_64__
hamaji
2014/03/24 15:56:37
Done.
| |
235 case __NR_time: | |
236 // This is obsolete in ARM EABI, but x86 glibc indirectly calls | |
237 // this in sysconf. | |
238 case __NR_modify_ldt: | |
239 // nacl_helper calls this from service_runtime/linux/x86/nacl_ldt.c | |
Mark Seaborn
2014/03/18 23:53:58
But this doesn't apply to Non-SFI Mode.
hamaji
2014/03/24 15:56:37
It seems current nacl_helper always calls NaClTlsI
| |
240 ret = ErrorCode(EPERM); | |
241 break; | |
242 #endif | |
243 | |
244 // Followings are restricted syscalls. | |
245 | |
246 // glibc internally calls brk in its memory allocation. | |
Mark Seaborn
2014/03/18 23:53:58
glibc does call brk(), but it doesn't require it t
jln (very slow on Chromium)
2014/03/20 00:54:53
Yes, in other words, just EPERM it.
hamaji
2014/03/24 15:56:37
Oops, my comment was wrong. brk was called by tcma
Mark Seaborn
2014/03/28 16:41:39
Does tcmalloc currently require brk(), or does it
| |
247 // TODO(hamaji): Uncomment this once newlib switch has been done. | |
248 // case __NR_brk: | |
249 case __NR_capget: | |
Mark Seaborn
2014/03/18 23:53:58
This is a blacklist of disallowed syscalls, but I
hamaji
2014/03/24 15:56:37
Done.
| |
250 case __NR_dup3: | |
251 case __NR_epoll_create1: | |
252 case __NR_fcntl: | |
253 case __NR_fork: | |
254 case __NR_get_robust_list: | |
255 case __NR_getgroups: | |
256 case __NR_getpid: | |
257 case __NR_getppid: | |
258 case __NR_getresgid: | |
259 case __NR_getresuid: | |
260 case __NR_getsid: | |
261 case __NR_kill: | |
262 case __NR_mlock: | |
263 case __NR_munlock: | |
264 case __NR_pause: | |
265 case __NR_pipe2: | |
266 case __NR_poll: | |
267 case __NR_ppoll: | |
268 case __NR_pselect6: | |
269 case __NR_readv: | |
270 case __NR_recvmmsg: | |
271 case __NR_rt_sigaction: | |
272 case __NR_sendmmsg: | |
273 case __NR_tgkill: | |
274 case __NR_tkill: | |
275 case __NR_wait4: | |
276 case __NR_waitid: | |
277 case __NR_writev: | |
278 // We do not need 32bit versions of them. | |
279 case __NR_fstat: | |
280 case __NR_lseek: | |
281 #if !defined(__arm__) | |
282 // They do not exist on ARM EABI. | |
283 case __NR_select: | |
284 #endif | |
285 #if defined(__i686__) | |
286 // This is i686 only. | |
287 case __NR_waitpid: | |
288 #endif | |
289 #if !defined(__i686__) | |
290 // i686 uses socketcall instead of them. | |
291 case __NR_sendto: | |
292 case __NR_shutdown: | |
293 case __NR_recvfrom: | |
294 #if defined(__arm__) | |
295 case __NR_send: | |
296 case __NR_recv: | |
297 #endif | |
298 #endif | |
299 #if !defined(__x86_64__) | |
300 // They do not exist on x86-64. | |
301 case __NR__newselect: | |
302 case __NR_getegid: | |
303 case __NR_geteuid: | |
304 case __NR_getgid: | |
305 case __NR_getgroups32: | |
306 case __NR_getresgid32: | |
307 case __NR_getresuid32: | |
308 case __NR_getuid: | |
309 case __NR_rt_sigprocmask: | |
310 case __NR_rt_sigreturn: | |
311 case __NR_sigprocmask: | |
312 case __NR_sigreturn: | |
313 #endif | |
314 ret = sb->Trap(sandbox::CrashSIGSYS_Handler, NULL); | |
315 break; | |
316 } | |
317 return ret; | |
318 } | |
319 | |
145 void RunSandboxSanityChecks() { | 320 void RunSandboxSanityChecks() { |
146 errno = 0; | 321 errno = 0; |
147 // Make a ptrace request with an invalid PID. | 322 // Make a ptrace request with an invalid PID. |
148 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); | 323 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); |
149 CHECK_EQ(-1, ptrace_ret); | 324 CHECK_EQ(-1, ptrace_ret); |
150 // Without the sandbox on, this ptrace call would ESRCH instead. | 325 // Without the sandbox on, this ptrace call would ESRCH instead. |
151 CHECK_EQ(EPERM, errno); | 326 CHECK_EQ(EPERM, errno); |
152 } | 327 } |
153 | 328 |
154 } // namespace | 329 } // namespace |
(...skipping 10 matching lines...) Expand all Loading... | |
165 #if defined(USE_SECCOMP_BPF) | 340 #if defined(USE_SECCOMP_BPF) |
166 bool sandbox_is_initialized = content::InitializeSandbox( | 341 bool sandbox_is_initialized = content::InitializeSandbox( |
167 scoped_ptr<SandboxBPFPolicy>(new NaClBPFSandboxPolicy())); | 342 scoped_ptr<SandboxBPFPolicy>(new NaClBPFSandboxPolicy())); |
168 if (sandbox_is_initialized) { | 343 if (sandbox_is_initialized) { |
169 RunSandboxSanityChecks(); | 344 RunSandboxSanityChecks(); |
170 return true; | 345 return true; |
171 } | 346 } |
172 #endif // defined(USE_SECCOMP_BPF) | 347 #endif // defined(USE_SECCOMP_BPF) |
173 return false; | 348 return false; |
174 } | 349 } |
350 | |
351 bool InitializeBPFSandboxForNonSfi() { | |
352 #if defined(USE_SECCOMP_BPF) | |
353 bool sandbox_is_initialized = content::InitializeSandbox( | |
hamaji
2014/03/14 12:46:23
I thought we should add something like
#if !defi
jln (very slow on Chromium)
2014/03/20 00:54:53
We should not return false in non SFI mode. We sho
hamaji
2014/03/24 15:56:37
Done.
| |
354 scoped_ptr<SandboxBPFPolicy>(new NonSfiNaClBPFSandboxPolicy())); | |
355 if (sandbox_is_initialized) { | |
356 RunSandboxSanityChecks(); | |
357 return true; | |
358 } | |
359 #endif // defined(USE_SECCOMP_BPF) | |
360 return false; | |
361 } | |
OLD | NEW |