X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fsandbox%2Flinux%2Fseccomp-bpf%2Fsandbox_bpf.h;h=d7fb1ff201746d24371b2c20b7f13a8254248eb6;hb=3545e9f2671f595d2a2f3ee75ca0393b01e35ef6;hp=f2653b077ac9c9d56b022e4916b1f8967635e483;hpb=4b53d56b8a1db20d4089f6d4f37126d43f907125;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/src/sandbox/linux/seccomp-bpf/sandbox_bpf.h index f2653b0..d7fb1ff 100644 --- a/src/sandbox/linux/seccomp-bpf/sandbox_bpf.h +++ b/src/sandbox/linux/seccomp-bpf/sandbox_bpf.h @@ -5,43 +5,27 @@ #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__ -#include -#include -#include +#include -#include -#include #include #include -#include #include -#include "sandbox/linux/seccomp-bpf/die.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "sandbox/linux/seccomp-bpf/errorcode.h" -#include "sandbox/linux/seccomp-bpf/linux_seccomp.h" -#include "sandbox/linux/seccomp-bpf/port.h" -#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy_forward.h" +#include "sandbox/linux/seccomp-bpf/trap.h" +#include "sandbox/sandbox_export.h" -namespace playground2 { - -struct arch_seccomp_data { - int nr; - uint32_t arch; - uint64_t instruction_pointer; - uint64_t args[6]; -}; - -struct arch_sigsys { - void *ip; - int nr; - unsigned int arch; -}; +struct sock_filter; +namespace sandbox { class CodeGen; +class SandboxBPFPolicy; class SandboxUnittestHelper; struct Instruction; -class Sandbox { +class SANDBOX_EXPORT SandboxBPF { public: enum SandboxStatus { STATUS_UNKNOWN, // Status prior to calling supportsSeccompSandbox() @@ -51,15 +35,17 @@ class Sandbox { STATUS_ENABLED // The sandbox is now active }; - // BpfSandboxPolicy is the following type: - // ErrorCode (Sandbox *sb, int sysnum, void *aux); - // When calling setSandboxPolicy(), the caller can provide an arbitrary - // pointer in |aux|. This pointer will then be forwarded to the sandbox - // policy each time a call is made through an EvaluateSyscall function - // pointer. One common use case would be to pass the "aux" pointer as an - // argument to Trap() functions. - typedef BpfSandboxPolicy* EvaluateSyscall; - typedef std::vector >Evaluators; + // Depending on the level of kernel support, seccomp-bpf may require the + // process to be single-threaded in order to enable it. When calling + // StartSandbox(), the program should indicate whether or not the sandbox + // should try and engage with multi-thread support. + enum SandboxThreadState { + PROCESS_INVALID, + PROCESS_SINGLE_THREADED, // The program is currently single-threaded. + // Note: PROCESS_MULTI_THREADED requires experimental kernel support that + // has not been contributed to upstream Linux. + PROCESS_MULTI_THREADED, // The program may be multi-threaded. + }; // A vector of BPF instructions that need to be installed as a filter // program in the kernel. @@ -75,8 +61,8 @@ class Sandbox { // should be noted that during its lifetime, the object probably made // irreversible state changes to the runtime environment. These changes // stay in effect even after the destructor has been run. - Sandbox(); - ~Sandbox(); + SandboxBPF(); + ~SandboxBPF(); // Checks whether a particular system call number is valid on the current // architecture. E.g. on ARM there's a non-contiguous range of private @@ -90,6 +76,10 @@ class Sandbox { // provided by the caller. static SandboxStatus SupportsSeccompSandbox(int proc_fd); + // Determines if the kernel has support for the seccomp() system call to + // synchronize BPF filters across a thread group. + static SandboxStatus SupportsSeccompThreadFilterSynchronization(); + // The sandbox needs to be able to access files in "/proc/self". If this // directory is not accessible when "startSandbox()" gets called, the caller // can provide an already opened file descriptor by calling "set_proc_fd()". @@ -97,18 +87,9 @@ class Sandbox { // eventually close it when "StartSandbox()" executes. void set_proc_fd(int proc_fd); - // The system call evaluator function is called with the system - // call number. It can decide to allow the system call unconditionally - // by returning ERR_ALLOWED; it can deny the system call unconditionally by - // returning an appropriate "errno" value; or it can request inspection - // of system call argument(s) by returning a suitable ErrorCode. - // The "aux" parameter can be used to pass optional data to the system call - // evaluator. There are different possible uses for this data, but one of the - // use cases would be for the policy to then forward this pointer to a Trap() - // handler. In this case, of course, the data that is pointed to must remain - // valid for the entire time that Trap() handlers can be called; typically, - // this would be the lifetime of the program. - void SetSandboxPolicy(EvaluateSyscall syscallEvaluator, void *aux); + // Set the BPF policy as |policy|. Ownership of |policy| is transfered here + // to the sandbox object. + void SetSandboxPolicy(SandboxBPFPolicy* policy); // We can use ErrorCode to request calling of a trap handler. This method // performs the required wrapping of the callback function into an @@ -116,7 +97,7 @@ class Sandbox { // The "aux" field can carry a pointer to arbitrary data. See EvaluateSyscall // for a description of how to pass data from SetSandboxPolicy() to a Trap() // handler. - ErrorCode Trap(Trap::TrapFnc fnc, const void *aux); + static ErrorCode Trap(Trap::TrapFnc fnc, const void* aux); // Calls a user-space trap handler and disables all sandboxing for system // calls made from this trap handler. @@ -128,7 +109,11 @@ class Sandbox { // very useful to diagnose code that is incompatible with the sandbox. // If even a single system call returns "UnsafeTrap", the security of // entire sandbox should be considered compromised. - ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void *aux); + static ErrorCode UnsafeTrap(Trap::TrapFnc fnc, const void* aux); + + // UnsafeTraps require some syscalls to always be allowed. + // This helper function returns true for these calls. + static bool IsRequiredForUnsafeTrap(int sysno); // From within an UnsafeTrap() it is often useful to be able to execute // the system call that triggered the trap. The ForwardSyscall() method @@ -143,24 +128,36 @@ class Sandbox { // We can also use ErrorCode to request evaluation of a conditional // statement based on inspection of system call parameters. // This method wrap an ErrorCode object around the conditional statement. - // Argument "argno" (1..6) will be compared to "value" using comparator - // "op". If the condition is true "passed" will be returned, otherwise - // "failed". + // Argument "argno" (1..6) will be bitwise-AND'd with "mask" and compared + // to "value"; if equal, then "passed" will be returned, otherwise "failed". // If "is32bit" is set, the argument must in the range of 0x0..(1u << 32 - 1) // If it is outside this range, the sandbox treats the system call just // the same as any other ABI violation (i.e. it aborts with an error // message). - ErrorCode Cond(int argno, ErrorCode::ArgType is_32bit, + ErrorCode CondMaskedEqual(int argno, + ErrorCode::ArgType is_32bit, + uint64_t mask, + uint64_t value, + const ErrorCode& passed, + const ErrorCode& failed); + + // Legacy variant of CondMaskedEqual that supports a few comparison + // operations, which get converted into masked-equality comparisons. + ErrorCode Cond(int argno, + ErrorCode::ArgType is_32bit, ErrorCode::Operation op, - uint64_t value, const ErrorCode& passed, + uint64_t value, + const ErrorCode& passed, const ErrorCode& failed); // Kill the program and print an error message. - ErrorCode Kill(const char *msg); + static ErrorCode Kill(const char* msg); // This is the main public entry point. It finds all system calls that // need rewriting, sets up the resources needed by the sandbox, and // enters Seccomp mode. + // The calling process must specify its current SandboxThreadState, as a way + // to tell the sandbox which type of kernel support it should engage. // It is possible to stack multiple sandboxes by creating separate "Sandbox" // objects and calling "StartSandbox()" on each of them. Please note, that // this requires special care, though, as newly stacked sandboxes can never @@ -169,7 +166,7 @@ class Sandbox { // disallowed. // Finally, stacking does add more kernel overhead than having a single // combined policy. So, it should only be used if there are no alternatives. - void StartSandbox(); + bool StartSandbox(SandboxThreadState thread_state) WARN_UNUSED_RESULT; // Assembles a BPF filter program from the current policy. After calling this // function, you must not call any other sandboxing function. @@ -179,12 +176,12 @@ class Sandbox { // through the verifier, iff the program was built in debug mode. // But by setting "force_verification", the caller can request that the // verifier is run unconditionally. This is useful for unittests. - Program *AssembleFilter(bool force_verification); + Program* AssembleFilter(bool force_verification); // Returns the fatal ErrorCode that is used to indicate that somebody // attempted to pass a 64bit value in a 32bit system call argument. // This method is primarily needed for testing purposes. - ErrorCode Unexpected64bitArgument(); + static ErrorCode Unexpected64bitArgument(); private: friend class CodeGen; @@ -193,17 +190,21 @@ class Sandbox { struct Range { Range(uint32_t f, uint32_t t, const ErrorCode& e) - : from(f), - to(t), - err(e) { - } - uint32_t from, to; + : from(f), to(t), err(e) {} + uint32_t from, to; ErrorCode err; }; typedef std::vector Ranges; typedef std::map ErrMap; typedef std::set Conds; + // Used by CondExpressionHalf to track which half of the argument it's + // emitting instructions for. + enum ArgHalf { + LowerHalf, + UpperHalf, + }; + // Get a file descriptor pointing to "/proc", if currently available. int proc_fd() { return proc_fd_; } @@ -211,7 +212,7 @@ class Sandbox { // policy. The caller has to make sure that "this" has not yet been // initialized with any other policies. bool RunFunctionInPolicy(void (*code_in_sandbox)(), - EvaluateSyscall syscall_evaluator, void *aux); + scoped_ptr policy); // Performs a couple of sanity checks to verify that the kernel supports the // features that we need for successful sandboxing. @@ -220,11 +221,42 @@ class Sandbox { bool KernelSupportSeccompBPF(); // Verify that the current policy passes some basic sanity checks. - void PolicySanityChecks(EvaluateSyscall syscall_evaluator, void *aux); + void PolicySanityChecks(SandboxBPFPolicy* policy); // Assembles and installs a filter based on the policy that has previously // been configured with SetSandboxPolicy(). - void InstallFilter(); + void InstallFilter(bool must_sync_threads); + + // Compile the configured policy into a complete instruction sequence. + // (See MaybeAddEscapeHatch for |has_unsafe_traps|.) + Instruction* CompilePolicy(CodeGen* gen, bool* has_unsafe_traps); + + // Return an instruction sequence that checks the + // arch_seccomp_data's "arch" field is valid, and then passes + // control to |passed| if so. + Instruction* CheckArch(CodeGen* gen, Instruction* passed); + + // If the |rest| instruction sequence contains any unsafe traps, + // then sets |*has_unsafe_traps| to true and returns an instruction + // sequence that allows all system calls from Syscall::Call(), and + // otherwise passes control to |rest|. + // + // If |rest| contains no unsafe traps, then |rest| is returned + // directly and |*has_unsafe_traps| is set to false. + Instruction* MaybeAddEscapeHatch(CodeGen* gen, + bool* has_unsafe_traps, + Instruction* rest); + + // Return an instruction sequence that loads and checks the system + // call number, performs a binary search, and then dispatches to an + // appropriate instruction sequence compiled from the current + // policy. + Instruction* DispatchSyscall(CodeGen* gen); + + // Return an instruction sequence that checks the system call number + // (expected to be loaded in register A) and if valid, passes + // control to |passed| (with register A still valid). + Instruction* CheckSyscallNumber(CodeGen* gen, Instruction* passed); // Verify the correctness of a compiled program by comparing it against the // current policy. This function should only ever be called by unit tests and @@ -235,11 +267,11 @@ class Sandbox { // sorted in ascending order of system call numbers. There are no gaps in the // ranges. System calls with identical ErrorCodes are coalesced into a single // range. - void FindRanges(Ranges *ranges); + void FindRanges(Ranges* ranges); // Returns a BPF program snippet that implements a jump table for the // given range of system call numbers. This function runs recursively. - Instruction *AssembleJumpTable(CodeGen *gen, + Instruction* AssembleJumpTable(CodeGen* gen, Ranges::const_iterator start, Ranges::const_iterator stop); @@ -248,24 +280,33 @@ class Sandbox { // conditional expression; if so, this function will recursively call // CondExpression() and possibly RetExpression() to build a complex set of // instructions. - Instruction *RetExpression(CodeGen *gen, const ErrorCode& err); + Instruction* RetExpression(CodeGen* gen, const ErrorCode& err); // Returns a BPF program that evaluates the conditional expression in // "cond" and returns the appropriate value from the BPF filter program. // This function recursively calls RetExpression(); it should only ever be // called from RetExpression(). - Instruction *CondExpression(CodeGen *gen, const ErrorCode& cond); + Instruction* CondExpression(CodeGen* gen, const ErrorCode& cond); + + // Returns a BPF program that evaluates half of a conditional expression; + // it should only ever be called from CondExpression(). + Instruction* CondExpressionHalf(CodeGen* gen, + const ErrorCode& cond, + ArgHalf half, + Instruction* passed, + Instruction* failed); static SandboxStatus status_; - bool quiet_; - int proc_fd_; - Evaluators *evaluators_; - Conds *conds_; + bool quiet_; + int proc_fd_; + scoped_ptr policy_; + Conds* conds_; + bool sandbox_has_started_; - DISALLOW_COPY_AND_ASSIGN(Sandbox); + DISALLOW_COPY_AND_ASSIGN(SandboxBPF); }; -} // namespace +} // namespace sandbox #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H__