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

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf.h

Issue 759473002: Linux sandbox: change seccomp detection and initialization. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor_startsandbox
Patch Set: Appease dumb compilers. Created 6 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 5 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__
6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 6 #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "sandbox/linux/seccomp-bpf/codegen.h" 13 #include "sandbox/linux/seccomp-bpf/codegen.h"
14 #include "sandbox/sandbox_export.h" 14 #include "sandbox/sandbox_export.h"
15 15
16 namespace sandbox { 16 namespace sandbox {
17 struct arch_seccomp_data; 17 struct arch_seccomp_data;
18 namespace bpf_dsl { 18 namespace bpf_dsl {
19 class Policy; 19 class Policy;
20 } 20 }
21 21
22 class SANDBOX_EXPORT SandboxBPF { 22 class SANDBOX_EXPORT SandboxBPF {
23 public: 23 public:
24 enum SandboxStatus { 24 enum class SeccompLevel {
25 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() 25 INVALID = 0,
mdempsky 2014/11/25 20:39:06 Currently the only use of this value is to check t
jln (very slow on Chromium) 2014/11/25 20:58:12 Yeah, true that it doesn't make a ton of sense any
26 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing 26 SINGLE_THREADED,
27 STATUS_UNAVAILABLE, // Currently unavailable but might work again later 27 MULTI_THREADED,
28 STATUS_AVAILABLE, // Sandboxing is available but not currently active
29 STATUS_ENABLED // The sandbox is now active
30 };
31
32 // Depending on the level of kernel support, seccomp-bpf may require the
33 // process to be single-threaded in order to enable it. When calling
34 // StartSandbox(), the program should indicate whether or not the sandbox
35 // should try and engage with multi-thread support.
36 enum SandboxThreadState {
37 PROCESS_INVALID,
38 PROCESS_SINGLE_THREADED, // The program is currently single-threaded.
39 // Note: PROCESS_MULTI_THREADED requires experimental kernel support that
40 // has not been contributed to upstream Linux.
41 PROCESS_MULTI_THREADED, // The program may be multi-threaded.
42 }; 28 };
43 29
44 // Constructors and destructors. 30 // Constructors and destructors.
45 // NOTE: Setting a policy and starting the sandbox is a one-way operation. 31 // NOTE: Setting a policy and starting the sandbox is a one-way operation.
46 // The kernel does not provide any option for unloading a loaded 32 // The kernel does not provide any option for unloading a loaded sandbox. The
47 // sandbox. Strictly speaking, that means we should disallow calling 33 // sandbox remains engaged even when the object is destructed.
48 // the destructor, if StartSandbox() has ever been called. In practice,
49 // this makes it needlessly complicated to operate on "Sandbox"
50 // objects. So, we instead opted to allow object destruction. But it
51 // should be noted that during its lifetime, the object probably made
52 // irreversible state changes to the runtime environment. These changes
53 // stay in effect even after the destructor has been run.
54 SandboxBPF(); 34 SandboxBPF();
55 ~SandboxBPF(); 35 ~SandboxBPF();
56 36
57 // Checks whether a particular system call number is valid on the current 37 // Checks whether a particular system call number is valid on the current
58 // architecture. E.g. on ARM there's a non-contiguous range of private 38 // architecture. E.g. on ARM there's a non-contiguous range of private
59 // system calls. 39 // system calls.
60 static bool IsValidSyscallNumber(int sysnum); 40 static bool IsValidSyscallNumber(int sysnum);
61 41
62 // Detect if the kernel supports the seccomp sandbox. The result of calling 42 // Detect if the kernel supports the specified seccomp level.
63 // this function will be cached. The first time this function is called, the 43 // See StartSandbox() for a description of these.
64 // running process must be unsandboxed (able to use /proc) and monothreaded. 44 static bool SupportsSeccompSandbox(SeccompLevel level);
65 static SandboxStatus SupportsSeccompSandbox();
66
67 // Determines if the kernel has support for the seccomp() system call to
68 // synchronize BPF filters across a thread group.
69 static SandboxStatus SupportsSeccompThreadFilterSynchronization();
70 45
71 // The sandbox needs to be able to access files in "/proc/self/task/". If 46 // The sandbox needs to be able to access files in "/proc/self/task/". If
72 // this directory is not accessible when "startSandbox()" gets called, the 47 // this directory is not accessible when "startSandbox()" gets called, the
73 // caller must provide an already opened file descriptor by calling 48 // caller must provide an already opened file descriptor by calling
74 // "set_proc_task_fd()". 49 // "set_proc_task_fd()".
75 // The sandbox becomes the new owner of this file descriptor and will 50 // The sandbox becomes the new owner of this file descriptor and will
76 // eventually close it when "StartSandbox()" executes. 51 // eventually close it when "StartSandbox()" executes.
77 void set_proc_task_fd(int proc_task_fd); 52 void set_proc_task_fd(int proc_task_fd);
78 53
79 // Set the BPF policy as |policy|. Ownership of |policy| is transfered here 54 // Set the BPF policy as |policy|. Ownership of |policy| is transfered here
80 // to the sandbox object. 55 // to the sandbox object.
81 void SetSandboxPolicy(bpf_dsl::Policy* policy); 56 void SetSandboxPolicy(bpf_dsl::Policy* policy);
82 57
83 // UnsafeTraps require some syscalls to always be allowed. 58 // UnsafeTraps require some syscalls to always be allowed.
84 // This helper function returns true for these calls. 59 // This helper function returns true for these calls.
85 static bool IsRequiredForUnsafeTrap(int sysno); 60 static bool IsRequiredForUnsafeTrap(int sysno);
86 61
87 // From within an UnsafeTrap() it is often useful to be able to execute 62 // From within an UnsafeTrap() it is often useful to be able to execute
88 // the system call that triggered the trap. The ForwardSyscall() method 63 // the system call that triggered the trap. The ForwardSyscall() method
89 // makes this easy. It is more efficient than calling glibc's syscall() 64 // makes this easy. It is more efficient than calling glibc's syscall()
90 // function, as it avoid the extra round-trip to the signal handler. And 65 // function, as it avoid the extra round-trip to the signal handler. And
91 // it automatically does the correct thing to report kernel-style error 66 // it automatically does the correct thing to report kernel-style error
92 // conditions, rather than setting errno. See the comments for TrapFnc for 67 // conditions, rather than setting errno. See the comments for TrapFnc for
93 // details. In other words, the return value from ForwardSyscall() is 68 // details. In other words, the return value from ForwardSyscall() is
94 // directly suitable as a return value for a trap handler. 69 // directly suitable as a return value for a trap handler.
95 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); 70 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args);
96 71
97 // This is the main public entry point. It finds all system calls that 72 // This is the main public entry point. It sets up the resources needed by
98 // need rewriting, sets up the resources needed by the sandbox, and 73 // the sandbox, and enters Seccomp mode.
99 // enters Seccomp mode. 74 // The calling process must provide a |level| to tell the sandbox which type
100 // The calling process must specify its current SandboxThreadState, as a way 75 // of kernel support it should engage.
101 // to tell the sandbox which type of kernel support it should engage. 76 // SINGLE_THREADED will only sandbox the calling thread. Since it would be a
77 // security risk, the sandbox will also check that the current process is
78 // single threaded.
79 // MULTI_THREADED requires more recent kernel support and allows to sandbox
80 // all the threads of the current process. Be mindful of potential races,
81 // with other threads using disallowed system calls either before or after
82 // the sandbox is engaged.
83 //
102 // It is possible to stack multiple sandboxes by creating separate "Sandbox" 84 // It is possible to stack multiple sandboxes by creating separate "Sandbox"
103 // objects and calling "StartSandbox()" on each of them. Please note, that 85 // objects and calling "StartSandbox()" on each of them. Please note, that
104 // this requires special care, though, as newly stacked sandboxes can never 86 // this requires special care, though, as newly stacked sandboxes can never
105 // relax restrictions imposed by earlier sandboxes. Furthermore, installing 87 // relax restrictions imposed by earlier sandboxes. Furthermore, installing
106 // a new policy requires making system calls, that might already be 88 // a new policy requires making system calls, that might already be
107 // disallowed. 89 // disallowed.
108 // Finally, stacking does add more kernel overhead than having a single 90 // Finally, stacking does add more kernel overhead than having a single
109 // combined policy. So, it should only be used if there are no alternatives. 91 // combined policy. So, it should only be used if there are no alternatives.
110 bool StartSandbox(SandboxThreadState thread_state) WARN_UNUSED_RESULT; 92 bool StartSandbox(SeccompLevel level) WARN_UNUSED_RESULT;
111 93
112 // Assembles a BPF filter program from the current policy. After calling this 94 // Assembles a BPF filter program from the current policy. After calling this
113 // function, you must not call any other sandboxing function. 95 // function, you must not call any other sandboxing function.
114 // Typically, AssembleFilter() is only used by unit tests and by sandbox 96 // Typically, AssembleFilter() is only used by unit tests and by sandbox
115 // internals. It should not be used by production code. 97 // internals. It should not be used by production code.
116 // For performance reasons, we normally only run the assembled BPF program 98 // For performance reasons, we normally only run the assembled BPF program
117 // through the verifier, iff the program was built in debug mode. 99 // through the verifier, iff the program was built in debug mode.
118 // But by setting "force_verification", the caller can request that the 100 // But by setting "force_verification", the caller can request that the
119 // verifier is run unconditionally. This is useful for unittests. 101 // verifier is run unconditionally. This is useful for unittests.
120 scoped_ptr<CodeGen::Program> AssembleFilter(bool force_verification); 102 scoped_ptr<CodeGen::Program> AssembleFilter(bool force_verification);
121 103
122 private: 104 private:
123 // Get a file descriptor pointing to "/proc", if currently available. 105 // Get a file descriptor pointing to "/proc", if currently available.
124 int proc_task_fd() { return proc_task_fd_; } 106 int proc_task_fd() { return proc_task_fd_; }
125 107
126 // Creates a subprocess and runs "code_in_sandbox" inside of the specified 108 // Creates a subprocess and runs "code_in_sandbox" inside of the specified
127 // policy. The caller has to make sure that "this" has not yet been 109 // policy. The caller has to make sure that "this" has not yet been
128 // initialized with any other policies. 110 // initialized with any other policies.
129 bool RunFunctionInPolicy(void (*code_in_sandbox)(), 111 bool RunFunctionInPolicy(void (*code_in_sandbox)(),
130 scoped_ptr<bpf_dsl::Policy> policy); 112 scoped_ptr<bpf_dsl::Policy> policy);
131 113
132 // Performs a couple of sanity checks to verify that the kernel supports the
133 // features that we need for successful sandboxing.
134 // The caller has to make sure that "this" has not yet been initialized with
135 // any other policies.
136 bool KernelSupportSeccompBPF();
137
138 // Assembles and installs a filter based on the policy that has previously 114 // Assembles and installs a filter based on the policy that has previously
139 // been configured with SetSandboxPolicy(). 115 // been configured with SetSandboxPolicy().
140 void InstallFilter(bool must_sync_threads); 116 void InstallFilter(bool must_sync_threads);
141 117
142 // Verify the correctness of a compiled program by comparing it against the 118 // Verify the correctness of a compiled program by comparing it against the
143 // current policy. This function should only ever be called by unit tests and 119 // current policy. This function should only ever be called by unit tests and
144 // by the sandbox internals. It should not be used by production code. 120 // by the sandbox internals. It should not be used by production code.
145 void VerifyProgram(const CodeGen::Program& program); 121 void VerifyProgram(const CodeGen::Program& program);
146 122
147 static SandboxStatus status_;
148
149 bool quiet_; 123 bool quiet_;
150 int proc_task_fd_; 124 int proc_task_fd_;
151 bool sandbox_has_started_; 125 bool sandbox_has_started_;
152 scoped_ptr<bpf_dsl::Policy> policy_; 126 scoped_ptr<bpf_dsl::Policy> policy_;
153 127
154 DISALLOW_COPY_AND_ASSIGN(SandboxBPF); 128 DISALLOW_COPY_AND_ASSIGN(SandboxBPF);
155 }; 129 };
156 130
157 } // namespace sandbox 131 } // namespace sandbox
158 132
159 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 133 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__
OLDNEW
« no previous file with comments | « sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc ('k') | sandbox/linux/seccomp-bpf/sandbox_bpf.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698