115 lines
4.7 KiB
C++
115 lines
4.7 KiB
C++
// 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 <memory>
|
|
|
|
#include "base/files/scoped_file.h"
|
|
#include "base/macros.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_;
|
|
std::unique_ptr<bpf_dsl::Policy> policy_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(SandboxBPF);
|
|
};
|
|
|
|
} // namespace sandbox
|
|
|
|
#endif // SANDBOX_LINUX_SECCOMP_BPF_SANDBOX_BPF_H_
|