Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc

Issue 114483003: Revert of Linux Sandbox: split the GPU policies to their own file. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 <asm/unistd.h>
6 #include <dlfcn.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <linux/net.h>
10 #include <signal.h>
11 #include <string.h>
12 #include <sys/ioctl.h>
13 #include <sys/mman.h>
14 #include <sys/prctl.h>
15 #include <sys/socket.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <ucontext.h>
19 #include <unistd.h>
20
21 #include <vector>
22
23 #include "base/basictypes.h"
24 #include "base/command_line.h"
25 #include "base/logging.h"
26 #include "build/build_config.h"
27 #include "content/public/common/content_switches.h"
28
29 // These are the only architectures supported for now.
30 #if defined(__i386__) || defined(__x86_64__) || \
31 (defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)))
32 #define SECCOMP_BPF_SANDBOX
33 #endif
34
35 #if defined(SECCOMP_BPF_SANDBOX)
36 #include "base/posix/eintr_wrapper.h"
37 #include "content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h"
38 #include "content/common/sandbox_linux/bpf_gpu_policy_linux.h"
39 #include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
40 #include "content/common/sandbox_linux/sandbox_linux.h"
41 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
42 #include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
43 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
44 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
45 #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
46 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
47 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
48 #include "sandbox/linux/services/linux_syscalls.h"
49
50 using sandbox::BaselinePolicy;
51 using sandbox::ErrorCode;
52 using sandbox::SandboxBPF;
53 using sandbox::SyscallSets;
54 using sandbox::arch_seccomp_data;
55
56 namespace content {
57
58 namespace {
59
60 void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy);
61
62 inline bool IsChromeOS() {
63 #if defined(OS_CHROMEOS)
64 return true;
65 #else
66 return false;
67 #endif
68 }
69
70 inline bool IsArchitectureArm() {
71 #if defined(__arm__)
72 return true;
73 #else
74 return false;
75 #endif
76 }
77
78 inline bool IsUsingToolKitGtk() {
79 #if defined(TOOLKIT_GTK)
80 return true;
81 #else
82 return false;
83 #endif
84 }
85
86 // Policy for renderer and worker processes.
87 // TODO(jln): move to renderer/
88
89 class RendererOrWorkerProcessPolicy : public SandboxBPFBasePolicy {
90 public:
91 RendererOrWorkerProcessPolicy() {}
92 virtual ~RendererOrWorkerProcessPolicy() {}
93
94 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
95 int system_call_number) const OVERRIDE;
96
97 private:
98 DISALLOW_COPY_AND_ASSIGN(RendererOrWorkerProcessPolicy);
99 };
100
101 ErrorCode RendererOrWorkerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
102 int sysno) const {
103 switch (sysno) {
104 case __NR_clone:
105 return sandbox::RestrictCloneToThreadsAndEPERMFork(sandbox);
106 case __NR_ioctl:
107 return sandbox::RestrictIoctl(sandbox);
108 case __NR_prctl:
109 return sandbox::RestrictPrctl(sandbox);
110 // Allow the system calls below.
111 case __NR_fdatasync:
112 case __NR_fsync:
113 case __NR_getpriority:
114 #if defined(__i386__) || defined(__x86_64__)
115 case __NR_getrlimit:
116 #endif
117 #if defined(__i386__) || defined(__arm__)
118 case __NR_ugetrlimit:
119 #endif
120 case __NR_mremap: // See crbug.com/149834.
121 case __NR_pread64:
122 case __NR_pwrite64:
123 case __NR_sched_getaffinity:
124 case __NR_sched_get_priority_max:
125 case __NR_sched_get_priority_min:
126 case __NR_sched_getparam:
127 case __NR_sched_getscheduler:
128 case __NR_sched_setscheduler:
129 case __NR_setpriority:
130 case __NR_sysinfo:
131 case __NR_times:
132 case __NR_uname:
133 return ErrorCode(ErrorCode::ERR_ALLOWED);
134 case __NR_prlimit64:
135 return ErrorCode(EPERM); // See crbug.com/160157.
136 default:
137 if (IsUsingToolKitGtk()) {
138 #if defined(__x86_64__) || defined(__arm__)
139 if (SyscallSets::IsSystemVSharedMemory(sysno))
140 return ErrorCode(ErrorCode::ERR_ALLOWED);
141 #endif
142 #if defined(__i386__)
143 if (SyscallSets::IsSystemVIpc(sysno))
144 return ErrorCode(ErrorCode::ERR_ALLOWED);
145 #endif
146 }
147
148 // Default on the content baseline policy.
149 return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
150 }
151 }
152
153 // Policy for PPAPI plugins.
154 // TODO(jln): move to ppapi_plugin/.
155 class FlashProcessPolicy : public SandboxBPFBasePolicy {
156 public:
157 FlashProcessPolicy() {}
158 virtual ~FlashProcessPolicy() {}
159
160 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
161 int system_call_number) const OVERRIDE;
162
163 private:
164 DISALLOW_COPY_AND_ASSIGN(FlashProcessPolicy);
165 };
166
167 ErrorCode FlashProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
168 int sysno) const {
169 switch (sysno) {
170 case __NR_clone:
171 return sandbox::RestrictCloneToThreadsAndEPERMFork(sandbox);
172 case __NR_pread64:
173 case __NR_pwrite64:
174 case __NR_sched_get_priority_max:
175 case __NR_sched_get_priority_min:
176 case __NR_sched_getaffinity:
177 case __NR_sched_getparam:
178 case __NR_sched_getscheduler:
179 case __NR_sched_setscheduler:
180 case __NR_times:
181 return ErrorCode(ErrorCode::ERR_ALLOWED);
182 case __NR_ioctl:
183 return ErrorCode(ENOTTY); // Flash Access.
184 default:
185 if (IsUsingToolKitGtk()) {
186 #if defined(__x86_64__) || defined(__arm__)
187 if (SyscallSets::IsSystemVSharedMemory(sysno))
188 return ErrorCode(ErrorCode::ERR_ALLOWED);
189 #endif
190 #if defined(__i386__)
191 if (SyscallSets::IsSystemVIpc(sysno))
192 return ErrorCode(ErrorCode::ERR_ALLOWED);
193 #endif
194 }
195
196 // Default on the baseline policy.
197 return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
198 }
199 }
200
201 class BlacklistDebugAndNumaPolicy : public SandboxBPFBasePolicy {
202 public:
203 BlacklistDebugAndNumaPolicy() {}
204 virtual ~BlacklistDebugAndNumaPolicy() {}
205
206 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
207 int system_call_number) const OVERRIDE;
208
209 private:
210 DISALLOW_COPY_AND_ASSIGN(BlacklistDebugAndNumaPolicy);
211 };
212
213 ErrorCode BlacklistDebugAndNumaPolicy::EvaluateSyscall(SandboxBPF* sandbox,
214 int sysno) const {
215 if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
216 // TODO(jln) we should not have to do that in a trivial policy.
217 return ErrorCode(ENOSYS);
218 }
219 if (SyscallSets::IsDebug(sysno) || SyscallSets::IsNuma(sysno))
220 return sandbox->Trap(sandbox::CrashSIGSYS_Handler, NULL);
221
222 return ErrorCode(ErrorCode::ERR_ALLOWED);
223 }
224
225 class AllowAllPolicy : public SandboxBPFBasePolicy {
226 public:
227 AllowAllPolicy() {}
228 virtual ~AllowAllPolicy() {}
229
230 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
231 int system_call_number) const OVERRIDE;
232
233 private:
234 DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy);
235 };
236
237 // Allow all syscalls.
238 // This will still deny x32 or IA32 calls in 64 bits mode or
239 // 64 bits system calls in compatibility mode.
240 ErrorCode AllowAllPolicy::EvaluateSyscall(SandboxBPF*, int sysno) const {
241 if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
242 // TODO(jln) we should not have to do that in a trivial policy.
243 return ErrorCode(ENOSYS);
244 } else {
245 return ErrorCode(ErrorCode::ERR_ALLOWED);
246 }
247 }
248
249 // If a BPF policy is engaged for |process_type|, run a few sanity checks.
250 void RunSandboxSanityChecks(const std::string& process_type) {
251 if (process_type == switches::kRendererProcess ||
252 process_type == switches::kWorkerProcess ||
253 process_type == switches::kGpuProcess ||
254 process_type == switches::kPpapiPluginProcess) {
255 int syscall_ret;
256 errno = 0;
257
258 // Without the sandbox, this would EBADF.
259 syscall_ret = fchmod(-1, 07777);
260 CHECK_EQ(-1, syscall_ret);
261 CHECK_EQ(EPERM, errno);
262
263 // Run most of the sanity checks only in DEBUG mode to avoid a perf.
264 // impact.
265 #if !defined(NDEBUG)
266 // open() must be restricted.
267 syscall_ret = open("/etc/passwd", O_RDONLY);
268 CHECK_EQ(-1, syscall_ret);
269 CHECK_EQ(SandboxBPFBasePolicy::GetFSDeniedErrno(), errno);
270
271 // We should never allow the creation of netlink sockets.
272 syscall_ret = socket(AF_NETLINK, SOCK_DGRAM, 0);
273 CHECK_EQ(-1, syscall_ret);
274 CHECK_EQ(EPERM, errno);
275 #endif // !defined(NDEBUG)
276 }
277 }
278
279
280 // This function takes ownership of |policy|.
281 void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy) {
282 // Starting the sandbox is a one-way operation. The kernel doesn't allow
283 // us to unload a sandbox policy after it has been started. Nonetheless,
284 // in order to make the use of the "Sandbox" object easier, we allow for
285 // the object to be destroyed after the sandbox has been started. Note that
286 // doing so does not stop the sandbox.
287 SandboxBPF sandbox;
288 sandbox.SetSandboxPolicy(policy);
289 sandbox.StartSandbox();
290 }
291
292 // nacl_helper needs to be tiny and includes only part of content/
293 // in its dependencies. Make sure to not link things that are not needed.
294 #if !defined(IN_NACL_HELPER)
295 scoped_ptr<SandboxBPFBasePolicy> GetGpuProcessSandbox() {
296 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
297 bool allow_sysv_shm = false;
298 if (command_line.HasSwitch(switches::kGpuSandboxAllowSysVShm)) {
299 DCHECK(IsArchitectureArm());
300 allow_sysv_shm = true;
301 }
302
303 if (IsChromeOS() && IsArchitectureArm()) {
304 return scoped_ptr<SandboxBPFBasePolicy>(
305 new CrosArmGpuProcessPolicy(allow_sysv_shm));
306 } else {
307 return scoped_ptr<SandboxBPFBasePolicy>(new GpuProcessPolicy);
308 }
309 }
310
311 // Initialize the seccomp-bpf sandbox.
312 bool StartBPFSandbox(const CommandLine& command_line,
313 const std::string& process_type) {
314 scoped_ptr<SandboxBPFBasePolicy> policy;
315
316 if (process_type == switches::kGpuProcess) {
317 policy.reset(GetGpuProcessSandbox().release());
318 } else if (process_type == switches::kRendererProcess ||
319 process_type == switches::kWorkerProcess) {
320 policy.reset(new RendererOrWorkerProcessPolicy);
321 } else if (process_type == switches::kPpapiPluginProcess) {
322 policy.reset(new FlashProcessPolicy);
323 } else if (process_type == switches::kUtilityProcess) {
324 policy.reset(new BlacklistDebugAndNumaPolicy);
325 } else {
326 NOTREACHED();
327 policy.reset(new AllowAllPolicy);
328 }
329
330 CHECK(policy->PreSandboxHook());
331 StartSandboxWithPolicy(policy.release());
332
333 RunSandboxSanityChecks(process_type);
334 return true;
335 }
336 #else // defined(IN_NACL_HELPER)
337 bool StartBPFSandbox(const CommandLine& command_line,
338 const std::string& process_type) {
339 NOTREACHED();
340 // Avoid -Wunused-function with no-op code.
341 ignore_result(IsChromeOS);
342 ignore_result(IsArchitectureArm);
343 ignore_result(RunSandboxSanityChecks);
344 return false;
345 }
346 #endif // !defined(IN_NACL_HELPER)
347
348 } // namespace
349
350 #endif // SECCOMP_BPF_SANDBOX
351
352 // Is seccomp BPF globally enabled?
353 bool SandboxSeccompBPF::IsSeccompBPFDesired() {
354 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
355 if (!command_line.HasSwitch(switches::kNoSandbox) &&
356 !command_line.HasSwitch(switches::kDisableSeccompFilterSandbox)) {
357 return true;
358 } else {
359 return false;
360 }
361 }
362
363 bool SandboxSeccompBPF::ShouldEnableSeccompBPF(
364 const std::string& process_type) {
365 #if defined(SECCOMP_BPF_SANDBOX)
366 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
367 if (process_type == switches::kGpuProcess)
368 return !command_line.HasSwitch(switches::kDisableGpuSandbox);
369
370 return true;
371 #endif // SECCOMP_BPF_SANDBOX
372 return false;
373 }
374
375 bool SandboxSeccompBPF::SupportsSandbox() {
376 #if defined(SECCOMP_BPF_SANDBOX)
377 // TODO(jln): pass the saved proc_fd_ from the LinuxSandbox singleton
378 // here.
379 SandboxBPF::SandboxStatus bpf_sandbox_status =
380 SandboxBPF::SupportsSeccompSandbox(-1);
381 // Kernel support is what we are interested in here. Other status
382 // such as STATUS_UNAVAILABLE (has threads) still indicate kernel support.
383 // We make this a negative check, since if there is a bug, we would rather
384 // "fail closed" (expect a sandbox to be available and try to start it).
385 if (bpf_sandbox_status != SandboxBPF::STATUS_UNSUPPORTED) {
386 return true;
387 }
388 #endif
389 return false;
390 }
391
392 bool SandboxSeccompBPF::StartSandbox(const std::string& process_type) {
393 #if defined(SECCOMP_BPF_SANDBOX)
394 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
395
396 if (IsSeccompBPFDesired() && // Global switches policy.
397 ShouldEnableSeccompBPF(process_type) && // Process-specific policy.
398 SupportsSandbox()) {
399 // If the kernel supports the sandbox, and if the command line says we
400 // should enable it, enable it or die.
401 bool started_sandbox = StartBPFSandbox(command_line, process_type);
402 CHECK(started_sandbox);
403 return true;
404 }
405 #endif
406 return false;
407 }
408
409 bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
410 scoped_ptr<sandbox::SandboxBPFPolicy> policy) {
411 #if defined(SECCOMP_BPF_SANDBOX)
412 if (IsSeccompBPFDesired() && SupportsSandbox()) {
413 CHECK(policy);
414 StartSandboxWithPolicy(policy.release());
415 return true;
416 }
417 #endif // defined(SECCOMP_BPF_SANDBOX)
418 return false;
419 }
420
421 scoped_ptr<sandbox::SandboxBPFPolicy>
422 SandboxSeccompBPF::GetBaselinePolicy() {
423 #if defined(SECCOMP_BPF_SANDBOX)
424 return scoped_ptr<sandbox::SandboxBPFPolicy>(new BaselinePolicy);
425 #else
426 return scoped_ptr<sandbox::SandboxBPFPolicy>();
427 #endif // defined(SECCOMP_BPF_SANDBOX)
428 }
429
430 } // namespace content
OLDNEW
« no previous file with comments | « content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h ('k') | content/common/sandbox_seccomp_bpf_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698