| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_ |
| #define SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_ |
| |
| #include <stdint.h> |
| |
| #include "base/files/scoped_file.h" |
| #include "base/macros.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "sandbox/linux/bpf_dsl/codegen.h" |
| #include "sandbox/sandbox_export.h" |
| |
| namespace sandbox { |
| struct arch_seccomp_data; |
| namespace bpf_dsl { |
| class Policy; |
| } |
| |
| // This class can be used to apply a syscall sandboxing policy expressed in a |
| // bpf_dsl::Policy object to the current process. |
| // Syscall sandboxing policies get inherited by subprocesses and, once applied, |
| // can never be removed for the lifetime of the process. |
| class SANDBOX_EXPORT SandboxBPF { |
| public: |
| enum class SeccompLevel { |
| SINGLE_THREADED, |
| MULTI_THREADED, |
| }; |
| |
| // Ownership of |policy| is transfered here to the sandbox object. |
| // nullptr is allowed for unit tests. |
| explicit SandboxBPF(bpf_dsl::Policy* policy); |
| // NOTE: Setting a policy and starting the sandbox is a one-way operation. |
| // The kernel does not provide any option for unloading a loaded sandbox. The |
| // sandbox remains engaged even when the object is destructed. |
| ~SandboxBPF(); |
| |
| // Detect if the kernel supports the specified seccomp level. |
| // See StartSandbox() for a description of these. |
| static bool SupportsSeccompSandbox(SeccompLevel level); |
| |
| // This is the main public entry point. It sets up the resources needed by |
| // the sandbox, and enters Seccomp mode. |
| // The calling process must provide a |level| to tell the sandbox which type |
| // of kernel support it should engage. |
| // SINGLE_THREADED will only sandbox the calling thread. Since it would be a |
| // security risk, the sandbox will also check that the current process is |
| // single threaded and crash if it isn't the case. |
| // MULTI_THREADED requires more recent kernel support and allows to sandbox |
| // all the threads of the current process. Be mindful of potential races, |
| // with other threads using disallowed system calls either before or after |
| // the sandbox is engaged. |
| // |
| // 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 |
| // relax restrictions imposed by earlier sandboxes. Furthermore, installing |
| // a new policy requires making system calls, that might already be |
| // 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. |
| bool StartSandbox(SeccompLevel level) WARN_UNUSED_RESULT; |
| |
| // The sandbox needs to be able to access files in "/proc/self/". If |
| // this directory is not accessible when "StartSandbox()" gets called, the |
| // caller must provide an already opened file descriptor by calling |
| // "SetProcFd()". |
| // The sandbox becomes the new owner of this file descriptor and will |
| // close it when "StartSandbox()" executes or when the sandbox object |
| // disappears. |
| void SetProcFd(base::ScopedFD proc_fd); |
| |
| // Checks whether a particular system call number is valid on the current |
| // architecture. |
| static bool IsValidSyscallNumber(int sysnum); |
| |
| // 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 |
| // makes this easy. It is more efficient than calling glibc's syscall() |
| // function, as it avoid the extra round-trip to the signal handler. And |
| // it automatically does the correct thing to report kernel-style error |
| // conditions, rather than setting errno. See the comments for TrapFnc for |
| // details. In other words, the return value from ForwardSyscall() is |
| // directly suitable as a return value for a trap handler. |
| static intptr_t ForwardSyscall(const struct arch_seccomp_data& args); |
| |
| private: |
| friend class SandboxBPFTestRunner; |
| |
| // Assembles a BPF filter program from the current policy. After calling this |
| // function, you must not call any other sandboxing function. |
| CodeGen::Program AssembleFilter(); |
| |
| // Assembles and installs a filter based on the policy that has previously |
| // been configured with SetSandboxPolicy(). |
| void InstallFilter(bool must_sync_threads); |
| |
| base::ScopedFD proc_fd_; |
| bool sandbox_has_started_; |
| scoped_ptr<bpf_dsl::Policy> policy_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SandboxBPF); |
| }; |
| |
| } // namespace sandbox |
| |
| #endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_ |