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

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

Issue 11411254: SECCOMP-BPF: Added supported for inspection system call arguments from BPF filters. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changelist is ready for initial review; still needs a few TODO()s to be resolved, though. Created 8 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
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 <endian.h> 8 #include <endian.h>
9 #include <errno.h> 9 #include <errno.h>
10 #include <fcntl.h> 10 #include <fcntl.h>
(...skipping 19 matching lines...) Expand all
30 #include <sys/stat.h> 30 #include <sys/stat.h>
31 #include <sys/types.h> 31 #include <sys/types.h>
32 #include <sys/uio.h> 32 #include <sys/uio.h>
33 #include <sys/wait.h> 33 #include <sys/wait.h>
34 #include <time.h> 34 #include <time.h>
35 #include <unistd.h> 35 #include <unistd.h>
36 36
37 #include <algorithm> 37 #include <algorithm>
38 #include <limits> 38 #include <limits>
39 #include <map> 39 #include <map>
40 #include <set>
40 #include <utility> 41 #include <utility>
41 #include <vector> 42 #include <vector>
42 43
43 #ifndef SECCOMP_BPF_STANDALONE 44 #ifndef SECCOMP_BPF_STANDALONE
44 #include "base/basictypes.h" 45 #include "base/basictypes.h"
45 #include "base/logging.h" 46 #include "base/logging.h"
46 #include "base/posix/eintr_wrapper.h" 47 #include "base/posix/eintr_wrapper.h"
47 #endif 48 #endif
48 49
49 #if defined(SECCOMP_BPF_VALGRIND_HACKS) 50 #if defined(SECCOMP_BPF_VALGRIND_HACKS)
(...skipping 12 matching lines...) Expand all
62 #define PR_GET_NO_NEW_PRIVS 39 63 #define PR_GET_NO_NEW_PRIVS 39
63 #endif 64 #endif
64 #ifndef IPC_64 65 #ifndef IPC_64
65 #define IPC_64 0x0100 66 #define IPC_64 0x0100
66 #endif 67 #endif
67 #ifndef SECCOMP_MODE_FILTER 68 #ifndef SECCOMP_MODE_FILTER
68 #define SECCOMP_MODE_DISABLED 0 69 #define SECCOMP_MODE_DISABLED 0
69 #define SECCOMP_MODE_STRICT 1 70 #define SECCOMP_MODE_STRICT 1
70 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter 71 #define SECCOMP_MODE_FILTER 2 // User user-supplied filter
71 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately 72 #define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately
73 #define SECCOMP_RET_INVALID 0x00010000U // Illegal return value
jln (very slow on Chromium) 2012/12/06 00:35:00 Maybe make it clear that's it's not an upstream va
Markus (顧孟勤) 2012/12/12 20:54:35 We cannot uncomment the include statement, as the
72 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS 74 #define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS
73 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno 75 #define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno
74 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow 76 #define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow
75 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow 77 #define SECCOMP_RET_ALLOW 0x7fff0000U // Allow
76 #define SECCOMP_RET_INVALID 0x8f8f8f8fU // Illegal return value
77 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value 78 #define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value
78 #define SECCOMP_RET_DATA 0x0000ffffU // sections 79 #define SECCOMP_RET_DATA 0x0000ffffU // sections
79 #endif 80 #endif
80 #define SECCOMP_DENY_ERRNO EPERM 81 #define SECCOMP_DENY_ERRNO EPERM
81 #ifndef SYS_SECCOMP 82 #ifndef SYS_SECCOMP
82 #define SYS_SECCOMP 1 83 #define SYS_SECCOMP 1
83 #endif 84 #endif
84 85
85 // Impose some reasonable maximum BPF program size. Realistically, the 86 // Impose some reasonable maximum BPF program size. Realistically, the
86 // kernel probably has much lower limits. But by limiting to less than 87 // kernel probably has much lower limits. But by limiting to less than
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 // Please note that TrapFnc is executed from signal context and must be 214 // Please note that TrapFnc is executed from signal context and must be
214 // async-signal safe: 215 // async-signal safe:
215 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html 216 // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
216 // Also note that it follows the calling convention of native system calls. 217 // Also note that it follows the calling convention of native system calls.
217 // In other words, it reports an error by returning an exit code in the 218 // In other words, it reports an error by returning an exit code in the
218 // range -1..-4096. It should not set errno when reporting errors; on the 219 // range -1..-4096. It should not set errno when reporting errors; on the
219 // other hand, accidentally modifying errno is harmless and the changes will 220 // other hand, accidentally modifying errno is harmless and the changes will
220 // be undone afterwards. 221 // be undone afterwards.
221 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); 222 typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux);
222 223
223 enum Operation {
224 OP_NOP, OP_EQUAL, OP_NOTEQUAL, OP_LESS,
225 OP_LESS_EQUAL, OP_GREATER, OP_GREATER_EQUAL,
226 OP_HAS_BITS, OP_DOES_NOT_HAVE_BITS
227 };
228
229 struct Constraint {
230 bool is32bit;
231 Operation op;
232 uint32_t value;
233 ErrorCode passed;
234 ErrorCode failed;
235 };
236
237 // When calling setSandboxPolicy(), the caller can provide an arbitrary 224 // When calling setSandboxPolicy(), the caller can provide an arbitrary
238 // pointer. This pointer will then be forwarded to the sandbox policy 225 // pointer. This pointer will then be forwarded to the sandbox policy
239 // each time a call is made through an EvaluateSyscall function pointer. 226 // each time a call is made through an EvaluateSyscall function pointer.
240 // One common use case would be to pass the "aux" pointer as an argument 227 // One common use case would be to pass the "aux" pointer as an argument
241 // to Trap() functions. 228 // to Trap() functions.
242 typedef ErrorCode (*EvaluateSyscall)(int sysnum, void *aux); 229 typedef ErrorCode (*EvaluateSyscall)(int sysnum, void *aux);
243 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators; 230 typedef std::vector<std::pair<EvaluateSyscall, void *> >Evaluators;
244 231
245 // Checks whether a particular system call number is valid on the current 232 // Checks whether a particular system call number is valid on the current
246 // architecture. E.g. on ARM there's a non-contiguous range of private 233 // architecture. E.g. on ARM there's a non-contiguous range of private
247 // system calls. 234 // system calls.
248 static bool isValidSyscallNumber(int sysnum); 235 static bool IsValidSyscallNumber(int sysnum);
249 236
250 // There are a lot of reasons why the Seccomp sandbox might not be available. 237 // There are a lot of reasons why the Seccomp sandbox might not be available.
251 // This could be because the kernel does not support Seccomp mode, or it 238 // This could be because the kernel does not support Seccomp mode, or it
252 // could be because another sandbox is already active. 239 // could be because another sandbox is already active.
253 // "proc_fd" should be a file descriptor for "/proc", or -1 if not 240 // "proc_fd" should be a file descriptor for "/proc", or -1 if not
254 // provided by the caller. 241 // provided by the caller.
255 static SandboxStatus supportsSeccompSandbox(int proc_fd); 242 static SandboxStatus SupportsSeccompSandbox(int proc_fd);
256 243
257 // The sandbox needs to be able to access files in "/proc/self". If this 244 // The sandbox needs to be able to access files in "/proc/self". If this
258 // directory is not accessible when "startSandbox()" gets called, the caller 245 // directory is not accessible when "startSandbox()" gets called, the caller
259 // can provide an already opened file descriptor by calling "setProcFd()". 246 // can provide an already opened file descriptor by calling "setProcFd()".
260 // The sandbox becomes the new owner of this file descriptor and will 247 // The sandbox becomes the new owner of this file descriptor and will
261 // eventually close it when "startSandbox()" executes. 248 // eventually close it when "startSandbox()" executes.
262 static void setProcFd(int proc_fd); 249 static void SetProcFd(int proc_fd);
263 250
264 // The system call evaluator function is called with the system 251 // The system call evaluator function is called with the system
265 // call number. It can decide to allow the system call unconditionally 252 // call number. It can decide to allow the system call unconditionally
266 // by returning ERR_ALLOWED; it can deny the system call unconditionally by 253 // by returning ERR_ALLOWED; it can deny the system call unconditionally by
267 // returning an appropriate "errno" value; or it can request inspection 254 // returning an appropriate "errno" value; or it can request inspection
268 // of system call argument(s) by returning a suitable ErrorCode. 255 // of system call argument(s) by returning a suitable ErrorCode.
269 // The "aux" parameter can be used to pass optional data to the system call 256 // The "aux" parameter can be used to pass optional data to the system call
270 // evaluator. There are different possible uses for this data, but one of the 257 // evaluator. There are different possible uses for this data, but one of the
271 // use cases would be for the policy to then forward this pointer to a Trap() 258 // use cases would be for the policy to then forward this pointer to a Trap()
272 // handler. In this case, of course, the data that is pointed to must remain 259 // handler. In this case, of course, the data that is pointed to must remain
273 // valid for the entire time that Trap() handlers can be called; typically, 260 // valid for the entire time that Trap() handlers can be called; typically,
274 // this would be the lifetime of the program. 261 // this would be the lifetime of the program.
275 static void setSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); 262 static void SetSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux);
276 263
277 // We can use ErrorCode to request calling of a trap handler. This method 264 // We can use ErrorCode to request calling of a trap handler. This method
278 // performs the required wrapping of the callback function into an 265 // performs the required wrapping of the callback function into an
279 // ErrorCode object. 266 // ErrorCode object.
280 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall 267 // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall
281 // for a description of how to pass data from setSandboxPolicy() to a Trap() 268 // for a description of how to pass data from setSandboxPolicy() to a Trap()
282 // handler. 269 // handler.
283 static ErrorCode Trap(ErrorCode::TrapFnc fnc, const void *aux); 270 static ErrorCode Trap(ErrorCode::TrapFnc fnc, const void *aux);
284 271
285 // Calls a user-space trap handler and disables all sandboxing for system 272 // Calls a user-space trap handler and disables all sandboxing for system
286 // calls made from this trap handler. 273 // calls made from this trap handler.
287 // NOTE: This feature, by definition, disables all security features of 274 // NOTE: This feature, by definition, disables all security features of
288 // the sandbox. It should never be used in production, but it can be 275 // the sandbox. It should never be used in production, but it can be
289 // very useful to diagnose code that is incompatible with the sandbox. 276 // very useful to diagnose code that is incompatible with the sandbox.
290 // If even a single system call returns "UnsafeTrap", the security of 277 // If even a single system call returns "UnsafeTrap", the security of
291 // entire sandbox should be considered compromised. 278 // entire sandbox should be considered compromised.
292 static ErrorCode UnsafeTrap(ErrorCode::TrapFnc fnc, const void *aux); 279 static ErrorCode UnsafeTrap(ErrorCode::TrapFnc fnc, const void *aux);
293 280
294 // From within an UnsafeTrap() it is often useful to be able to execute 281 // From within an UnsafeTrap() it is often useful to be able to execute
295 // the system call that triggered the trap. The ForwardSyscall() method 282 // the system call that triggered the trap. The ForwardSyscall() method
296 // makes this easy. It is more efficient than calling glibc's syscall() 283 // makes this easy. It is more efficient than calling glibc's syscall()
297 // function, as it avoid the extra round-trip to the signal handler. And 284 // function, as it avoid the extra round-trip to the signal handler. And
298 // it automatically does the correct thing to report kernel-style error 285 // it automatically does the correct thing to report kernel-style error
299 // conditions, rather than setting errno. See the comments for TrapFnc for 286 // conditions, rather than setting errno. See the comments for TrapFnc for
300 // details. In other words, the return value from ForwardSyscall() is 287 // details. In other words, the return value from ForwardSyscall() is
301 // directly suitable as a return value for a trap handler. 288 // directly suitable as a return value for a trap handler.
302 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); 289 static intptr_t ForwardSyscall(const struct arch_seccomp_data& args);
303 290
291 // We can also use ErrorCode to request evaluation of a conditional
292 // statement based on inspection of system call parameters.
293 // This method wrap an ErrorCode object around the conditional statement.
294 // Argument "argno" (1..6) will be compared to "value" using comparator
295 // "op". If the condition is true "passed" will be returned, otherwise
296 // "failed".
297 // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1)
298 // If it is outside this range, the sandbox treats the system call just
299 // the same as any other ABI violation (i.e. it aborts with an error
300 // message).
301 static ErrorCode Cond(int argno, ErrorCode::ArgType is_32bit,
302 ErrorCode::Operation op,
303 uint64_t value, const ErrorCode& passed,
304 const ErrorCode& failed);
305
304 // Kill the program and print an error message. 306 // Kill the program and print an error message.
305 static ErrorCode Kill(const char *msg); 307 static ErrorCode Kill(const char *msg);
306 308
307 // This is the main public entry point. It finds all system calls that 309 // This is the main public entry point. It finds all system calls that
308 // need rewriting, sets up the resources needed by the sandbox, and 310 // need rewriting, sets up the resources needed by the sandbox, and
309 // enters Seccomp mode. 311 // enters Seccomp mode.
310 static void startSandbox() { startSandboxInternal(false); } 312 static void StartSandbox() { StartSandboxInternal(false); }
311 313
312 private: 314 private:
313 friend class ErrorCode;
314 friend class CodeGen; 315 friend class CodeGen;
315 friend class SandboxUnittestHelper; 316 friend class SandboxUnittestHelper;
317 friend class ErrorCode;
316 friend class Util; 318 friend class Util;
317 friend class Verifier; 319 friend class Verifier;
318 320
319 typedef std::vector<struct sock_filter> Program; 321 typedef std::vector<struct sock_filter> Program;
320 322
321 struct Range { 323 struct Range {
322 Range(uint32_t f, uint32_t t, const ErrorCode& e) 324 Range(uint32_t f, uint32_t t, const ErrorCode& e)
323 : from(f), 325 : from(f),
324 to(t), 326 to(t),
325 err(e) { 327 err(e) {
326 } 328 }
327 uint32_t from, to; 329 uint32_t from, to;
328 ErrorCode err; 330 ErrorCode err;
329 }; 331 };
330 struct TrapKey { 332 struct TrapKey {
331 TrapKey(TrapFnc f, const void *a, bool s) 333 TrapKey(TrapFnc f, const void *a, bool s)
332 : fnc(f), 334 : fnc(f),
333 aux(a), 335 aux(a),
334 safe(s) { 336 safe(s) {
335 } 337 }
336 TrapFnc fnc; 338 TrapFnc fnc;
337 const void *aux; 339 const void *aux;
338 bool safe; 340 bool safe;
339 bool operator<(const TrapKey&) const; 341 bool operator<(const TrapKey&) const;
340 }; 342 };
341 typedef std::vector<Range> Ranges; 343 typedef std::vector<Range> Ranges;
342 typedef std::map<uint32_t, ErrorCode> ErrMap; 344 typedef std::map<uint32_t, ErrorCode> ErrMap;
343 typedef std::vector<ErrorCode> Traps; 345 typedef std::vector<ErrorCode> Traps;
344 typedef std::map<TrapKey, uint16_t> TrapIds; 346 typedef std::map<TrapKey, uint16_t> TrapIds;
347 typedef std::set<ErrorCode, struct ErrorCode::LessThan> Conds;
345 348
346 // Get a file descriptor pointing to "/proc", if currently available. 349 // Get a file descriptor pointing to "/proc", if currently available.
347 static int proc_fd() { return proc_fd_; } 350 static int ProcFd() { return proc_fd_; }
348 351
349 static ErrorCode probeEvaluator(int sysnum, void *) __attribute__((const)); 352 static ErrorCode ProbeEvaluator(int sysnum, void *) __attribute__((const));
350 static void probeProcess(void); 353 static void ProbeProcess(void);
351 static ErrorCode allowAllEvaluator(int sysnum, void *aux); 354 static ErrorCode AllowAllEvaluator(int sysnum, void *aux);
352 static void tryVsyscallProcess(void); 355 static void TryVsyscallProcess(void);
353 static bool kernelSupportSeccompBPF(int proc_fd); 356 static bool KernelSupportSeccompBPF(int proc_fd);
354 static bool RunFunctionInPolicy(void (*function)(), 357 static bool RunFunctionInPolicy(void (*function)(),
355 EvaluateSyscall syscallEvaluator, 358 EvaluateSyscall syscall_evaluator,
356 void *aux, 359 void *aux,
357 int proc_fd); 360 int proc_fd);
358 static void startSandboxInternal(bool quiet); 361 static void StartSandboxInternal(bool quiet);
359 static bool isSingleThreaded(int proc_fd); 362 static bool IsSingleThreaded(int proc_fd);
360 static bool isDenied(const ErrorCode& code); 363 static bool IsDenied(const ErrorCode& code);
361 static bool disableFilesystem(); 364 static bool DisableFilesystem();
362 static void policySanityChecks(EvaluateSyscall syscallEvaluator, 365 static void PolicySanityChecks(EvaluateSyscall syscall_evaluator,
363 void *aux); 366 void *aux);
364 367
365 // Function that can be passed as a callback function to CodeGen::Traverse(). 368 // Function that can be passed as a callback function to CodeGen::Traverse().
366 // Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it 369 // Checks whether the "insn" returns an UnsafeTrap() ErrorCode. If so, it
367 // sets the "bool" variable pointed to by "aux". 370 // sets the "bool" variable pointed to by "aux".
368 static void CheckForUnsafeErrorCodes(Instruction *insn, void *aux); 371 static void CheckForUnsafeErrorCodes(Instruction *insn, void *aux);
369 372
370 // Function that can be passed as a callback function to CodeGen::Traverse(). 373 // Function that can be passed as a callback function to CodeGen::Traverse().
371 // Checks whether the "insn" returns an errno value from a BPF filter. If so, 374 // Checks whether the "insn" returns an errno value from a BPF filter. If so,
372 // it rewrites the instruction to instead call a Trap() handler that does 375 // it rewrites the instruction to instead call a Trap() handler that does
373 // the same thing. "aux" is ignored. 376 // the same thing. "aux" is ignored.
374 static void RedirectToUserspace(Instruction *insn, void *aux); 377 static void RedirectToUserspace(Instruction *insn, void *aux);
375 378
376 // Stackable wrapper around an Evaluators handler. Changes ErrorCodes 379 // Stackable wrapper around an Evaluators handler. Changes ErrorCodes
377 // returned by a system call evaluator to match the changes made by 380 // returned by a system call evaluator to match the changes made by
378 // RedirectToUserspace(). "aux" should be pointer to wrapped system call 381 // RedirectToUserspace(). "aux" should be pointer to wrapped system call
379 // evaluator. 382 // evaluator.
380 static ErrorCode RedirectToUserspaceEvalWrapper(int sysnum, void *aux); 383 static ErrorCode RedirectToUserspaceEvalWrapper(int sysnum, void *aux);
381 384
382 static void installFilter(bool quiet); 385 static void InstallFilter(bool quiet);
383 static void findRanges(Ranges *ranges); 386 static void FindRanges(Ranges *ranges);
384 static Instruction *assembleJumpTable(CodeGen *gen, 387 static Instruction *AssembleJumpTable(CodeGen *gen,
385 Ranges::const_iterator start, 388 Ranges::const_iterator start,
386 Ranges::const_iterator stop); 389 Ranges::const_iterator stop);
387 static void sigSys(int nr, siginfo_t *info, void *void_context); 390 static Instruction *RetExpression(CodeGen *gen, const ErrorCode& cond);
391 static Instruction *CondExpression(CodeGen *gen, const ErrorCode& cond);
392 static void SigSys(int nr, siginfo_t *info, void *void_context);
388 static ErrorCode MakeTrap(ErrorCode::TrapFnc fn, const void *aux, bool safe); 393 static ErrorCode MakeTrap(ErrorCode::TrapFnc fn, const void *aux, bool safe);
389 394
390 // A Trap() handler that returns an "errno" value. The value is encoded 395 // A Trap() handler that returns an "errno" value. The value is encoded
391 // in the "aux" parameter. 396 // in the "aux" parameter.
392 static intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux); 397 static intptr_t ReturnErrno(const struct arch_seccomp_data&, void *aux);
393 398
394 static intptr_t bpfFailure(const struct arch_seccomp_data& data, void *aux); 399 static intptr_t BpfFailure(const struct arch_seccomp_data& data, void *aux);
395 static int getTrapId(TrapFnc fnc, const void *aux);
396 400
397 static SandboxStatus status_; 401 static SandboxStatus status_;
398 static int proc_fd_; 402 static int proc_fd_;
399 static Evaluators evaluators_; 403 static Evaluators evaluators_;
400 static Traps *traps_; 404 static Traps *traps_;
401 static TrapIds trapIds_; 405 static TrapIds trap_ids_;
402 static ErrorCode *trapArray_; 406 static ErrorCode *trap_array_;
403 static size_t trapArraySize_; 407 static size_t trap_array_size_;
404 static bool has_unsafe_traps_; 408 static bool has_unsafe_traps_;
409 static Conds conds_;
410
405 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox); 411 DISALLOW_IMPLICIT_CONSTRUCTORS(Sandbox);
406 }; 412 };
407 413
408 } // namespace 414 } // namespace
409 415
410 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ 416 #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698