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

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

Issue 66723007: Make sandbox/linux/seccomp-bpf/ follow the style guide. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: (empty) rebase Created 7 years, 1 month 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
« no previous file with comments | « sandbox/linux/seccomp-bpf/port.h ('k') | sandbox/linux/seccomp-bpf/sandbox_bpf.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stddef.h> 8 #include <stddef.h>
9 #include <sys/types.h> 9 #include <sys/types.h>
10 #include <sys/wait.h> 10 #include <sys/wait.h>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <limits> 13 #include <limits>
14 #include <map> 14 #include <map>
15 #include <set> 15 #include <set>
16 #include <utility> 16 #include <utility>
17 #include <vector> 17 #include <vector>
18 18
19 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/scoped_ptr.h"
20 #include "sandbox/linux/seccomp-bpf/die.h" 20 #include "sandbox/linux/seccomp-bpf/die.h"
21 #include "sandbox/linux/seccomp-bpf/errorcode.h" 21 #include "sandbox/linux/seccomp-bpf/errorcode.h"
22 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" 22 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
23 #include "sandbox/linux/seccomp-bpf/port.h" 23 #include "sandbox/linux/seccomp-bpf/port.h"
24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy_forward.h" 24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy_forward.h"
25 25
26 namespace playground2 { 26 namespace playground2 {
27 27
28 struct arch_seccomp_data { 28 struct arch_seccomp_data {
29 int nr; 29 int nr;
30 uint32_t arch; 30 uint32_t arch;
31 uint64_t instruction_pointer; 31 uint64_t instruction_pointer;
32 uint64_t args[6]; 32 uint64_t args[6];
33 }; 33 };
34 34
35 struct arch_sigsys { 35 struct arch_sigsys {
36 void *ip; 36 void* ip;
37 int nr; 37 int nr;
38 unsigned int arch; 38 unsigned int arch;
39 }; 39 };
40 40
41 class CodeGen; 41 class CodeGen;
42 class SandboxUnittestHelper; 42 class SandboxUnittestHelper;
43 class SandboxBpfPolicy; 43 class SandboxBpfPolicy;
44 struct Instruction; 44 struct Instruction;
45 45
46 class Sandbox { 46 class Sandbox {
47 public: 47 public:
48 enum SandboxStatus { 48 enum SandboxStatus {
49 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() 49 STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox()
50 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing 50 STATUS_UNSUPPORTED, // The kernel does not appear to support sandboxing
51 STATUS_UNAVAILABLE, // Currently unavailable but might work again later 51 STATUS_UNAVAILABLE, // Currently unavailable but might work again later
52 STATUS_AVAILABLE, // Sandboxing is available but not currently active 52 STATUS_AVAILABLE, // Sandboxing is available but not currently active
53 STATUS_ENABLED // The sandbox is now active 53 STATUS_ENABLED // The sandbox is now active
54 }; 54 };
55 55
56 // BpfSandboxPolicy is the following type: 56 // BpfSandboxPolicy is the following type:
57 // ErrorCode (Sandbox *sb, int sysnum, void *aux); 57 // ErrorCode (Sandbox *sb, int sysnum, void *aux);
58 // When calling setSandboxPolicy(), the caller can provide an arbitrary 58 // When calling setSandboxPolicy(), the caller can provide an arbitrary
59 // pointer in |aux|. This pointer will then be forwarded to the sandbox 59 // pointer in |aux|. This pointer will then be forwarded to the sandbox
60 // policy each time a call is made through an EvaluateSyscall function 60 // policy each time a call is made through an EvaluateSyscall function
61 // pointer. One common use case would be to pass the "aux" pointer as an 61 // pointer. One common use case would be to pass the "aux" pointer as an
62 // argument to Trap() functions. 62 // argument to Trap() functions.
63 typedef BpfSandboxPolicy* EvaluateSyscall; 63 typedef BpfSandboxPolicy* EvaluateSyscall;
64 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators; 64 typedef std::vector<std::pair<EvaluateSyscall, void*> > Evaluators;
65 65
66 // A vector of BPF instructions that need to be installed as a filter 66 // A vector of BPF instructions that need to be installed as a filter
67 // program in the kernel. 67 // program in the kernel.
68 typedef std::vector<struct sock_filter> Program; 68 typedef std::vector<struct sock_filter> Program;
69 69
70 // Constructors and destructors. 70 // Constructors and destructors.
71 // NOTE: Setting a policy and starting the sandbox is a one-way operation. 71 // NOTE: Setting a policy and starting the sandbox is a one-way operation.
72 // The kernel does not provide any option for unloading a loaded 72 // The kernel does not provide any option for unloading a loaded
73 // sandbox. Strictly speaking, that means we should disallow calling 73 // sandbox. Strictly speaking, that means we should disallow calling
74 // the destructor, if StartSandbox() has ever been called. In practice, 74 // the destructor, if StartSandbox() has ever been called. In practice,
(...skipping 29 matching lines...) Expand all
104 // by returning ERR_ALLOWED; it can deny the system call unconditionally by 104 // by returning ERR_ALLOWED; it can deny the system call unconditionally by
105 // returning an appropriate "errno" value; or it can request inspection 105 // returning an appropriate "errno" value; or it can request inspection
106 // of system call argument(s) by returning a suitable ErrorCode. 106 // of system call argument(s) by returning a suitable ErrorCode.
107 // The "aux" parameter can be used to pass optional data to the system call 107 // The "aux" parameter can be used to pass optional data to the system call
108 // evaluator. There are different possible uses for this data, but one of the 108 // evaluator. There are different possible uses for this data, but one of the
109 // use cases would be for the policy to then forward this pointer to a Trap() 109 // use cases would be for the policy to then forward this pointer to a Trap()
110 // handler. In this case, of course, the data that is pointed to must remain 110 // handler. In this case, of course, the data that is pointed to must remain
111 // valid for the entire time that Trap() handlers can be called; typically, 111 // valid for the entire time that Trap() handlers can be called; typically,
112 // this would be the lifetime of the program. 112 // this would be the lifetime of the program.
113 // DEPRECATED: use the policy interface below. 113 // DEPRECATED: use the policy interface below.
114 void SetSandboxPolicyDeprecated(EvaluateSyscall syscallEvaluator, void *aux); 114 void SetSandboxPolicyDeprecated(EvaluateSyscall syscallEvaluator, void* aux);
115 115
116 // Set the BPF policy as |policy|. Ownership of |policy| is transfered here 116 // Set the BPF policy as |policy|. Ownership of |policy| is transfered here
117 // to the sandbox object. 117 // to the sandbox object.
118 void SetSandboxPolicy(SandboxBpfPolicy* policy); 118 void SetSandboxPolicy(SandboxBpfPolicy* policy);
119 119
120 // We can use ErrorCode to request calling of a trap handler. This method 120 // We can use ErrorCode to request calling of a trap handler. This method
121 // performs the required wrapping of the callback function into an 121 // performs the required wrapping of the callback function into an
122 // ErrorCode object. 122 // ErrorCode object.
123 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall 123 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall
124 // for a description of how to pass data from SetSandboxPolicy() to a Trap() 124 // for a description of how to pass data from SetSandboxPolicy() to a Trap()
125 // handler. 125 // handler.
126 ErrorCode Trap(Trap::TrapFnc fnc, const void *aux); 126 ErrorCode Trap(Trap::TrapFnc fnc, const void* aux);
127 127
128 // Calls a user-space trap handler and disables all sandboxing for system 128 // Calls a user-space trap handler and disables all sandboxing for system
129 // calls made from this trap handler. 129 // calls made from this trap handler.
130 // This feature is available only if explicitly enabled by the user having 130 // This feature is available only if explicitly enabled by the user having
131 // set the CHROME_SANDBOX_DEBUGGING environment variable. 131 // set the CHROME_SANDBOX_DEBUGGING environment variable.
132 // Returns an ET_INVALID ErrorCode, if called when not enabled. 132 // Returns an ET_INVALID ErrorCode, if called when not enabled.
133 // NOTE: This feature, by definition, disables all security features of 133 // NOTE: This feature, by definition, disables all security features of
134 // the sandbox. It should never be used in production, but it can be 134 // the sandbox. It should never be used in production, but it can be
135 // very useful to diagnose code that is incompatible with the sandbox. 135 // very useful to diagnose code that is incompatible with the sandbox.
136 // If even a single system call returns "UnsafeTrap", the security of 136 // If even a single system call returns "UnsafeTrap", the security of
137 // entire sandbox should be considered compromised. 137 // entire sandbox should be considered compromised.
138 ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void *aux); 138 ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void* aux);
139 139
140 // From within an UnsafeTrap() it is often useful to be able to execute 140 // From within an UnsafeTrap() it is often useful to be able to execute
141 // the system call that triggered the trap. The ForwardSyscall() method 141 // the system call that triggered the trap. The ForwardSyscall() method
142 // makes this easy. It is more efficient than calling glibc's syscall() 142 // makes this easy. It is more efficient than calling glibc's syscall()
143 // function, as it avoid the extra round-trip to the signal handler. And 143 // function, as it avoid the extra round-trip to the signal handler. And
144 // it automatically does the correct thing to report kernel-style error 144 // it automatically does the correct thing to report kernel-style error
145 // conditions, rather than setting errno. See the comments for TrapFnc for 145 // conditions, rather than setting errno. See the comments for TrapFnc for
146 // details. In other words, the return value from ForwardSyscall() is 146 // details. In other words, the return value from ForwardSyscall() is
147 // directly suitable as a return value for a trap handler. 147 // directly suitable as a return value for a trap handler.
148 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); 148 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args);
149 149
150 // We can also use ErrorCode to request evaluation of a conditional 150 // We can also use ErrorCode to request evaluation of a conditional
151 // statement based on inspection of system call parameters. 151 // statement based on inspection of system call parameters.
152 // This method wrap an ErrorCode object around the conditional statement. 152 // This method wrap an ErrorCode object around the conditional statement.
153 // Argument "argno" (1..6) will be compared to "value" using comparator 153 // Argument "argno" (1..6) will be compared to "value" using comparator
154 // "op". If the condition is true "passed" will be returned, otherwise 154 // "op". If the condition is true "passed" will be returned, otherwise
155 // "failed". 155 // "failed".
156 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) 156 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1)
157 // If it is outside this range, the sandbox treats the system call just 157 // If it is outside this range, the sandbox treats the system call just
158 // the same as any other ABI violation (i.e. it aborts with an error 158 // the same as any other ABI violation (i.e. it aborts with an error
159 // message). 159 // message).
160 ErrorCode Cond(int argno, ErrorCode::ArgType is_32bit, 160 ErrorCode Cond(int argno,
161 ErrorCode::ArgType is_32bit,
161 ErrorCode::Operation op, 162 ErrorCode::Operation op,
162 uint64_t value, const ErrorCode& passed, 163 uint64_t value,
164 const ErrorCode& passed,
163 const ErrorCode& failed); 165 const ErrorCode& failed);
164 166
165 // Kill the program and print an error message. 167 // Kill the program and print an error message.
166 ErrorCode Kill(const char *msg); 168 ErrorCode Kill(const char* msg);
167 169
168 // This is the main public entry point. It finds all system calls that 170 // This is the main public entry point. It finds all system calls that
169 // need rewriting, sets up the resources needed by the sandbox, and 171 // need rewriting, sets up the resources needed by the sandbox, and
170 // enters Seccomp mode. 172 // enters Seccomp mode.
171 // It is possible to stack multiple sandboxes by creating separate "Sandbox" 173 // It is possible to stack multiple sandboxes by creating separate "Sandbox"
172 // objects and calling "StartSandbox()" on each of them. Please note, that 174 // objects and calling "StartSandbox()" on each of them. Please note, that
173 // this requires special care, though, as newly stacked sandboxes can never 175 // this requires special care, though, as newly stacked sandboxes can never
174 // relax restrictions imposed by earlier sandboxes. Furthermore, installing 176 // relax restrictions imposed by earlier sandboxes. Furthermore, installing
175 // a new policy requires making system calls, that might already be 177 // a new policy requires making system calls, that might already be
176 // disallowed. 178 // disallowed.
177 // Finally, stacking does add more kernel overhead than having a single 179 // Finally, stacking does add more kernel overhead than having a single
178 // combined policy. So, it should only be used if there are no alternatives. 180 // combined policy. So, it should only be used if there are no alternatives.
179 void StartSandbox(); 181 void StartSandbox();
180 182
181 // Assembles a BPF filter program from the current policy. After calling this 183 // Assembles a BPF filter program from the current policy. After calling this
182 // function, you must not call any other sandboxing function. 184 // function, you must not call any other sandboxing function.
183 // Typically, AssembleFilter() is only used by unit tests and by sandbox 185 // Typically, AssembleFilter() is only used by unit tests and by sandbox
184 // internals. It should not be used by production code. 186 // internals. It should not be used by production code.
185 // For performance reasons, we normally only run the assembled BPF program 187 // For performance reasons, we normally only run the assembled BPF program
186 // through the verifier, iff the program was built in debug mode. 188 // through the verifier, iff the program was built in debug mode.
187 // But by setting "force_verification", the caller can request that the 189 // But by setting "force_verification", the caller can request that the
188 // verifier is run unconditionally. This is useful for unittests. 190 // verifier is run unconditionally. This is useful for unittests.
189 Program *AssembleFilter(bool force_verification); 191 Program* AssembleFilter(bool force_verification);
190 192
191 // Returns the fatal ErrorCode that is used to indicate that somebody 193 // Returns the fatal ErrorCode that is used to indicate that somebody
192 // attempted to pass a 64bit value in a 32bit system call argument. 194 // attempted to pass a 64bit value in a 32bit system call argument.
193 // This method is primarily needed for testing purposes. 195 // This method is primarily needed for testing purposes.
194 ErrorCode Unexpected64bitArgument(); 196 ErrorCode Unexpected64bitArgument();
195 197
196 private: 198 private:
197 friend class CodeGen; 199 friend class CodeGen;
198 friend class SandboxUnittestHelper; 200 friend class SandboxUnittestHelper;
199 friend class ErrorCode; 201 friend class ErrorCode;
200 202
201 struct Range { 203 struct Range {
202 Range(uint32_t f, uint32_t t, const ErrorCode& e) 204 Range(uint32_t f, uint32_t t, const ErrorCode& e)
203 : from(f), 205 : from(f), to(t), err(e) {}
204 to(t), 206 uint32_t from, to;
205 err(e) {
206 }
207 uint32_t from, to;
208 ErrorCode err; 207 ErrorCode err;
209 }; 208 };
210 typedef std::vector<Range> Ranges; 209 typedef std::vector<Range> Ranges;
211 typedef std::map<uint32_t, ErrorCode> ErrMap; 210 typedef std::map<uint32_t, ErrorCode> ErrMap;
212 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds; 211 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds;
213 212
214 // Get a file descriptor pointing to "/proc", if currently available. 213 // Get a file descriptor pointing to "/proc", if currently available.
215 int proc_fd() { return proc_fd_; } 214 int proc_fd() { return proc_fd_; }
216 215
217 // Creates a subprocess and runs "code_in_sandbox" inside of the specified 216 // Creates a subprocess and runs "code_in_sandbox" inside of the specified
218 // policy. The caller has to make sure that "this" has not yet been 217 // policy. The caller has to make sure that "this" has not yet been
219 // initialized with any other policies. 218 // initialized with any other policies.
220 bool RunFunctionInPolicy(void (*code_in_sandbox)(), 219 bool RunFunctionInPolicy(void (*code_in_sandbox)(),
221 EvaluateSyscall syscall_evaluator, void *aux); 220 EvaluateSyscall syscall_evaluator,
221 void* aux);
222 222
223 // Performs a couple of sanity checks to verify that the kernel supports the 223 // Performs a couple of sanity checks to verify that the kernel supports the
224 // features that we need for successful sandboxing. 224 // features that we need for successful sandboxing.
225 // The caller has to make sure that "this" has not yet been initialized with 225 // The caller has to make sure that "this" has not yet been initialized with
226 // any other policies. 226 // any other policies.
227 bool KernelSupportSeccompBPF(); 227 bool KernelSupportSeccompBPF();
228 228
229 // Verify that the current policy passes some basic sanity checks. 229 // Verify that the current policy passes some basic sanity checks.
230 void PolicySanityChecks(SandboxBpfPolicy* policy); 230 void PolicySanityChecks(SandboxBpfPolicy* policy);
231 231
232 // Assembles and installs a filter based on the policy that has previously 232 // Assembles and installs a filter based on the policy that has previously
233 // been configured with SetSandboxPolicy(). 233 // been configured with SetSandboxPolicy().
234 void InstallFilter(); 234 void InstallFilter();
235 235
236 // Verify the correctness of a compiled program by comparing it against the 236 // Verify the correctness of a compiled program by comparing it against the
237 // current policy. This function should only ever be called by unit tests and 237 // current policy. This function should only ever be called by unit tests and
238 // by the sandbox internals. It should not be used by production code. 238 // by the sandbox internals. It should not be used by production code.
239 void VerifyProgram(const Program& program, bool has_unsafe_traps); 239 void VerifyProgram(const Program& program, bool has_unsafe_traps);
240 240
241 // Finds all the ranges of system calls that need to be handled. Ranges are 241 // Finds all the ranges of system calls that need to be handled. Ranges are
242 // sorted in ascending order of system call numbers. There are no gaps in the 242 // sorted in ascending order of system call numbers. There are no gaps in the
243 // ranges. System calls with identical ErrorCodes are coalesced into a single 243 // ranges. System calls with identical ErrorCodes are coalesced into a single
244 // range. 244 // range.
245 void FindRanges(Ranges *ranges); 245 void FindRanges(Ranges* ranges);
246 246
247 // Returns a BPF program snippet that implements a jump table for the 247 // Returns a BPF program snippet that implements a jump table for the
248 // given range of system call numbers. This function runs recursively. 248 // given range of system call numbers. This function runs recursively.
249 Instruction *AssembleJumpTable(CodeGen *gen, 249 Instruction* AssembleJumpTable(CodeGen* gen,
250 Ranges::const_iterator start, 250 Ranges::const_iterator start,
251 Ranges::const_iterator stop); 251 Ranges::const_iterator stop);
252 252
253 // Returns a BPF program snippet that makes the BPF filter program exit 253 // Returns a BPF program snippet that makes the BPF filter program exit
254 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a 254 // with the given ErrorCode "err". N.B. the ErrorCode may very well be a
255 // conditional expression; if so, this function will recursively call 255 // conditional expression; if so, this function will recursively call
256 // CondExpression() and possibly RetExpression() to build a complex set of 256 // CondExpression() and possibly RetExpression() to build a complex set of
257 // instructions. 257 // instructions.
258 Instruction *RetExpression(CodeGen *gen, const ErrorCode& err); 258 Instruction* RetExpression(CodeGen* gen, const ErrorCode& err);
259 259
260 // Returns a BPF program that evaluates the conditional expression in 260 // Returns a BPF program that evaluates the conditional expression in
261 // "cond" and returns the appropriate value from the BPF filter program. 261 // "cond" and returns the appropriate value from the BPF filter program.
262 // This function recursively calls RetExpression(); it should only ever be 262 // This function recursively calls RetExpression(); it should only ever be
263 // called from RetExpression(). 263 // called from RetExpression().
264 Instruction *CondExpression(CodeGen *gen, const ErrorCode& cond); 264 Instruction* CondExpression(CodeGen* gen, const ErrorCode& cond);
265 265
266 static SandboxStatus status_; 266 static SandboxStatus status_;
267 267
268 bool quiet_; 268 bool quiet_;
269 int proc_fd_; 269 int proc_fd_;
270 scoped_ptr<const SandboxBpfPolicy> policy_; 270 scoped_ptr<const SandboxBpfPolicy> policy_;
271 Conds* conds_; 271 Conds* conds_;
272 bool sandbox_has_started_; 272 bool sandbox_has_started_;
273 273
274 DISALLOW_COPY_AND_ASSIGN(Sandbox); 274 DISALLOW_COPY_AND_ASSIGN(Sandbox);
275 }; 275 };
276 276
277 } // namespace 277 } // namespace
278 278
279 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 279 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/port.h ('k') | sandbox/linux/seccomp-bpf/sandbox_bpf.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698