This source file includes following definitions.
- IsChromeOS
- IsArchitectureArm
- EvaluateSyscall
- EvaluateSyscall
- RunSandboxSanityChecks
- StartSandboxWithPolicy
- GetGpuProcessSandbox
- StartBPFSandbox
- StartBPFSandbox
- IsSeccompBPFDesired
- ShouldEnableSeccompBPF
- SupportsSandbox
- StartSandbox
- StartSandboxWithExternalPolicy
- GetBaselinePolicy
#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/types.h>
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
#if defined(USE_SECCOMP_BPF)
#include "base/posix/eintr_wrapper.h"
#include "content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h"
#include "content/common/sandbox_linux/bpf_gpu_policy_linux.h"
#include "content/common/sandbox_linux/bpf_ppapi_policy_linux.h"
#include "content/common/sandbox_linux/bpf_renderer_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/services/linux_syscalls.h"
using sandbox::BaselinePolicy;
using sandbox::SyscallSets;
#else
#if !defined(ARCH_CPU_MIPS_FAMILY)
#error "Seccomp-bpf disabled on supported architecture!"
#endif
#endif
namespace content {
#if defined(USE_SECCOMP_BPF)
namespace {
void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy);
inline bool IsChromeOS() {
#if defined(OS_CHROMEOS)
return true;
#else
return false;
#endif
}
inline bool IsArchitectureArm() {
#if defined(__arm__)
return true;
#else
return false;
#endif
}
class BlacklistDebugAndNumaPolicy : public SandboxBPFBasePolicy {
public:
BlacklistDebugAndNumaPolicy() {}
virtual ~BlacklistDebugAndNumaPolicy() {}
virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
int system_call_number) const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(BlacklistDebugAndNumaPolicy);
};
ErrorCode BlacklistDebugAndNumaPolicy::EvaluateSyscall(SandboxBPF* sandbox,
int sysno) const {
if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
return ErrorCode(ENOSYS);
}
if (SyscallSets::IsDebug(sysno) || SyscallSets::IsNuma(sysno))
return sandbox->Trap(sandbox::CrashSIGSYS_Handler, NULL);
return ErrorCode(ErrorCode::ERR_ALLOWED);
}
class AllowAllPolicy : public SandboxBPFBasePolicy {
public:
AllowAllPolicy() {}
virtual ~AllowAllPolicy() {}
virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
int system_call_number) const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy);
};
ErrorCode AllowAllPolicy::EvaluateSyscall(SandboxBPF*, int sysno) const {
if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
return ErrorCode(ENOSYS);
} else {
return ErrorCode(ErrorCode::ERR_ALLOWED);
}
}
void RunSandboxSanityChecks(const std::string& process_type) {
if (process_type == switches::kRendererProcess ||
process_type == switches::kWorkerProcess ||
process_type == switches::kGpuProcess ||
process_type == switches::kPpapiPluginProcess) {
int syscall_ret;
errno = 0;
syscall_ret = fchmod(-1, 07777);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(EPERM, errno);
#if !defined(NDEBUG)
syscall_ret = open("/etc/passwd", O_RDONLY);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(SandboxBPFBasePolicy::GetFSDeniedErrno(), errno);
syscall_ret = socket(AF_NETLINK, SOCK_DGRAM, 0);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(EPERM, errno);
#endif
}
}
void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy) {
SandboxBPF sandbox;
sandbox.SetSandboxPolicy(policy);
sandbox.StartSandbox();
}
#if !defined(IN_NACL_HELPER)
scoped_ptr<SandboxBPFBasePolicy> GetGpuProcessSandbox() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
bool allow_sysv_shm = false;
if (command_line.HasSwitch(switches::kGpuSandboxAllowSysVShm)) {
DCHECK(IsArchitectureArm());
allow_sysv_shm = true;
}
if (IsChromeOS() && IsArchitectureArm()) {
return scoped_ptr<SandboxBPFBasePolicy>(
new CrosArmGpuProcessPolicy(allow_sysv_shm));
} else {
return scoped_ptr<SandboxBPFBasePolicy>(new GpuProcessPolicy);
}
}
bool StartBPFSandbox(const CommandLine& command_line,
const std::string& process_type) {
scoped_ptr<SandboxBPFBasePolicy> policy;
if (process_type == switches::kGpuProcess) {
policy.reset(GetGpuProcessSandbox().release());
} else if (process_type == switches::kRendererProcess ||
process_type == switches::kWorkerProcess) {
policy.reset(new RendererProcessPolicy);
} else if (process_type == switches::kPpapiPluginProcess) {
policy.reset(new PpapiProcessPolicy);
} else if (process_type == switches::kUtilityProcess) {
policy.reset(new BlacklistDebugAndNumaPolicy);
} else {
NOTREACHED();
policy.reset(new AllowAllPolicy);
}
CHECK(policy->PreSandboxHook());
StartSandboxWithPolicy(policy.release());
RunSandboxSanityChecks(process_type);
return true;
}
#else
bool StartBPFSandbox(const CommandLine& command_line,
const std::string& process_type) {
NOTREACHED();
ignore_result(IsChromeOS);
ignore_result(IsArchitectureArm);
ignore_result(RunSandboxSanityChecks);
return false;
}
#endif
}
#endif
bool SandboxSeccompBPF::IsSeccompBPFDesired() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (!command_line.HasSwitch(switches::kNoSandbox) &&
!command_line.HasSwitch(switches::kDisableSeccompFilterSandbox)) {
return true;
} else {
return false;
}
}
bool SandboxSeccompBPF::ShouldEnableSeccompBPF(
const std::string& process_type) {
#if defined(USE_SECCOMP_BPF)
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (process_type == switches::kGpuProcess)
return !command_line.HasSwitch(switches::kDisableGpuSandbox);
return true;
#endif
return false;
}
bool SandboxSeccompBPF::SupportsSandbox() {
#if defined(USE_SECCOMP_BPF)
SandboxBPF::SandboxStatus bpf_sandbox_status =
SandboxBPF::SupportsSeccompSandbox(-1);
if (bpf_sandbox_status != SandboxBPF::STATUS_UNSUPPORTED) {
return true;
}
#endif
return false;
}
bool SandboxSeccompBPF::StartSandbox(const std::string& process_type) {
#if defined(USE_SECCOMP_BPF)
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (IsSeccompBPFDesired() &&
ShouldEnableSeccompBPF(process_type) &&
SupportsSandbox()) {
bool started_sandbox = StartBPFSandbox(command_line, process_type);
CHECK(started_sandbox);
return true;
}
#endif
return false;
}
bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
scoped_ptr<sandbox::SandboxBPFPolicy> policy) {
#if defined(USE_SECCOMP_BPF)
if (IsSeccompBPFDesired() && SupportsSandbox()) {
CHECK(policy);
StartSandboxWithPolicy(policy.release());
return true;
}
#endif
return false;
}
scoped_ptr<sandbox::SandboxBPFPolicy>
SandboxSeccompBPF::GetBaselinePolicy() {
#if defined(USE_SECCOMP_BPF)
return scoped_ptr<sandbox::SandboxBPFPolicy>(new BaselinePolicy);
#else
return scoped_ptr<sandbox::SandboxBPFPolicy>();
#endif
}
}