Commit a18b9943 authored by Tom Sepez's avatar Tom Sepez Committed by Commit Bot

CDM Utility process requires syscalls beyond utility.

Add SANDBOX_TYPE_WIDEVINE, and a policy for it. This value is
also special in that will also defers some initializations in a
subsequent CL.

Also parse --sandbox-type=ppapi for utility processes as
SANDBOX_TYPE_PPAPI, as a generic equivalent.

Tidy GetGpuProcessSandbox() since there was a blown merge around it
and I was looking at it.

TBR=jam@chromiuim.org

Bug: 765840
Change-Id: Ifdc0949f811c916b12f6d89b4fbd1ffdab61cd64
Reviewed-on: https://chromium-review.googlesource.com/671453
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#502956}
parent 31885d17
......@@ -95,6 +95,8 @@ if (is_component_build) {
"public/common/content_switches.h",
"public/common/mojo_channel_switches.cc",
"public/common/mojo_channel_switches.h",
"public/common/sandbox_type.cc",
"public/common/sandbox_type.h",
]
set_sources_assignment_filter(sources_assignment_filter)
......
......@@ -62,7 +62,9 @@ class UtilitySandboxedProcessLauncherDelegate
sandbox_type_(sandbox_type) {
DCHECK(sandbox_type_ == SANDBOX_TYPE_NO_SANDBOX ||
sandbox_type_ == SANDBOX_TYPE_UTILITY ||
sandbox_type_ == SANDBOX_TYPE_NETWORK);
sandbox_type_ == SANDBOX_TYPE_NETWORK ||
sandbox_type_ == SANDBOX_TYPE_WIDEVINE ||
sandbox_type_ == SANDBOX_TYPE_PPAPI);
}
~UtilitySandboxedProcessLauncherDelegate() override {}
......
......@@ -312,6 +312,8 @@ source_set("common") {
"sandbox_linux/bpf_renderer_policy_linux.h",
"sandbox_linux/bpf_utility_policy_linux.cc",
"sandbox_linux/bpf_utility_policy_linux.h",
"sandbox_linux/bpf_widevine_policy_linux.cc",
"sandbox_linux/bpf_widevine_policy_linux.h",
"sandbox_linux/sandbox_bpf_base_policy_linux.cc",
"sandbox_linux/sandbox_bpf_base_policy_linux.h",
"sandbox_linux/sandbox_debug_handling_linux.cc",
......
// Copyright 2017 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.
#include "content/common/sandbox_linux/bpf_widevine_policy_linux.h"
#include <errno.h>
#include "build/build_config.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
using sandbox::SyscallSets;
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::ResultExpr;
namespace content {
WidevineProcessPolicy::WidevineProcessPolicy() {}
WidevineProcessPolicy::~WidevineProcessPolicy() {}
ResultExpr WidevineProcessPolicy::EvaluateSyscall(int sysno) const {
switch (sysno) {
case __NR_ioctl:
return sandbox::RestrictIoctl();
// Allow the system calls below.
case __NR_fdatasync:
case __NR_fsync:
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
defined(__aarch64__)
case __NR_getrlimit:
#endif
#if defined(__i386__) || defined(__arm__)
case __NR_ugetrlimit:
#endif
case __NR_mremap: // https://crbug.com/546204
case __NR_pread64:
case __NR_pwrite64:
case __NR_sysinfo:
case __NR_times:
case __NR_uname:
return Allow();
case __NR_sched_getaffinity:
return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
default:
// Default on the content baseline policy.
return SandboxBPFBasePolicy::EvaluateSyscall(sysno);
}
}
} // namespace content
// Copyright 2017 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 CONTENT_COMMON_SANDBOX_LINUX_BPF_WIDEVINE_POLICY_LINUX_H_
#define CONTENT_COMMON_SANDBOX_LINUX_BPF_WIDEVINE_POLICY_LINUX_H_
#include "base/macros.h"
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
namespace content {
// This policy can be used by widevine processes.
class WidevineProcessPolicy : public SandboxBPFBasePolicy {
public:
WidevineProcessPolicy();
~WidevineProcessPolicy() override;
sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
int system_call_number) const override;
private:
DISALLOW_COPY_AND_ASSIGN(WidevineProcessPolicy);
};
} // namespace content
#endif // CONTENT_COMMON_SANDBOX_LINUX_BPF_WIDEVINE_POLICY_LINUX_H_
......@@ -17,6 +17,7 @@
#include "base/macros.h"
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/sandbox_type.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/sandbox_features.h"
......@@ -30,6 +31,7 @@
#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/bpf_utility_policy_linux.h"
#include "content/common/sandbox_linux/bpf_widevine_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
......@@ -131,72 +133,84 @@ inline bool IsArchitectureArm() {
}
// If a BPF policy is engaged for |process_type|, run a few sanity checks.
void RunSandboxSanityChecks(const std::string& process_type) {
if (process_type == switches::kRendererProcess ||
process_type == switches::kGpuProcess ||
process_type == switches::kPpapiPluginProcess) {
int syscall_ret;
errno = 0;
// Without the sandbox, this would EBADF.
syscall_ret = fchmod(-1, 07777);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(EPERM, errno);
// Run most of the sanity checks only in DEBUG mode to avoid a perf.
// impact.
void RunSandboxSanityChecks(SandboxType sandbox_type) {
switch (sandbox_type) {
case SANDBOX_TYPE_RENDERER:
case SANDBOX_TYPE_GPU:
case SANDBOX_TYPE_PPAPI:
case SANDBOX_TYPE_WIDEVINE: {
int syscall_ret;
errno = 0;
// Without the sandbox, this would EBADF.
syscall_ret = fchmod(-1, 07777);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(EPERM, errno);
// Run most of the sanity checks only in DEBUG mode to avoid a perf.
// impact.
#if !defined(NDEBUG)
// open() must be restricted.
syscall_ret = open("/etc/passwd", O_RDONLY);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(SandboxBPFBasePolicy::GetFSDeniedErrno(), errno);
// We should never allow the creation of netlink sockets.
syscall_ret = socket(AF_NETLINK, SOCK_DGRAM, 0);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(EPERM, errno);
// open() must be restricted.
syscall_ret = open("/etc/passwd", O_RDONLY);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(SandboxBPFBasePolicy::GetFSDeniedErrno(), errno);
// We should never allow the creation of netlink sockets.
syscall_ret = socket(AF_NETLINK, SOCK_DGRAM, 0);
CHECK_EQ(-1, syscall_ret);
CHECK_EQ(EPERM, errno);
#endif // !defined(NDEBUG)
} break;
default:
// Otherwise, no checks required.
break;
}
}
std::unique_ptr<SandboxBPFBasePolicy> GetGpuProcessSandbox(
const gpu::GPUInfo* gpu_info) {
if (IsChromeOS() && IsArchitectureArm()) {
return std::make_unique<CrosArmGpuProcessPolicy>(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kGpuSandboxAllowSysVShm));
}
uint32_t gpu_vendor = 0;
if (gpu_info != NULL)
gpu_vendor = gpu_info->active_gpu().vendor_id;
if (IsChromeOS() && angle::IsAMD(gpu_vendor)) {
return std::unique_ptr<SandboxBPFBasePolicy>(
new CrosAmdGpuProcessPolicy());
if (IsChromeOS()) {
if (IsArchitectureArm()) {
return std::make_unique<CrosArmGpuProcessPolicy>(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kGpuSandboxAllowSysVShm));
}
if (gpu_info && angle::IsAMD(gpu_info->active_gpu().vendor_id))
return std::make_unique<CrosAmdGpuProcessPolicy>();
}
return std::make_unique<GpuProcessPolicy>();
}
// Initialize the seccomp-bpf sandbox.
bool StartBPFSandbox(const base::CommandLine& command_line,
const std::string& process_type,
bool StartBPFSandbox(SandboxType sandbox_type,
base::ScopedFD proc_fd,
const gpu::GPUInfo* gpu_info) {
std::unique_ptr<SandboxBPFBasePolicy> policy;
if (process_type == switches::kGpuProcess) {
policy = GetGpuProcessSandbox(gpu_info);
} else if (process_type == switches::kRendererProcess) {
policy = std::make_unique<RendererProcessPolicy>();
} else if (process_type == switches::kPpapiPluginProcess) {
policy = std::make_unique<PpapiProcessPolicy>();
} else if (process_type == switches::kUtilityProcess) {
policy = std::make_unique<UtilityProcessPolicy>();
} else {
NOTREACHED();
policy = std::make_unique<AllowAllPolicy>();
switch (sandbox_type) {
case SANDBOX_TYPE_GPU:
policy = GetGpuProcessSandbox(gpu_info);
break;
case SANDBOX_TYPE_RENDERER:
policy = std::make_unique<RendererProcessPolicy>();
break;
case SANDBOX_TYPE_PPAPI:
policy = std::make_unique<PpapiProcessPolicy>();
break;
case SANDBOX_TYPE_UTILITY:
policy = std::make_unique<UtilityProcessPolicy>();
break;
case SANDBOX_TYPE_WIDEVINE:
policy = std::make_unique<WidevineProcessPolicy>();
break;
case SANDBOX_TYPE_NO_SANDBOX:
default:
NOTREACHED();
policy = std::make_unique<AllowAllPolicy>();
break;
}
CHECK(policy->PreSandboxHook());
StartSandboxWithPolicy(std::move(policy), std::move(proc_fd));
RunSandboxSanityChecks(process_type);
RunSandboxSanityChecks(sandbox_type);
return true;
}
#endif // !defined(IN_NACL_HELPER)
......@@ -247,16 +261,14 @@ bool SandboxSeccompBPF::StartSandbox(const std::string& process_type,
base::ScopedFD proc_fd,
const gpu::GPUInfo* gpu_info) {
#if BUILDFLAG(USE_SECCOMP_BPF)
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (IsSeccompBPFDesired() && // Global switches policy.
ShouldEnableSeccompBPF(process_type) && // Process-specific policy.
SupportsSandbox()) {
// If the kernel supports the sandbox, and if the command line says we
// should enable it, enable it or die.
CHECK(StartBPFSandbox(command_line, process_type, std::move(proc_fd),
gpu_info));
CHECK(StartBPFSandbox(
SandboxTypeFromCommandLine(*base::CommandLine::ForCurrentProcess()),
std::move(proc_fd), gpu_info));
return true;
}
#endif
......
......@@ -62,6 +62,7 @@ SandboxTypeToResourceIDMapping kDefaultSandboxTypeToResourceIDMapping[] = {
{SANDBOX_TYPE_GPU, IDR_GPU_SANDBOX_PROFILE},
{SANDBOX_TYPE_PPAPI, IDR_PPAPI_SANDBOX_PROFILE},
{SANDBOX_TYPE_NETWORK, -1},
{SANDBOX_TYPE_WIDEVINE, IDR_PPAPI_SANDBOX_PROFILE},
};
static_assert(arraysize(kDefaultSandboxTypeToResourceIDMapping) == \
......
......@@ -10,6 +10,18 @@
namespace content {
namespace {
// Must be in sync with "sandbox_type" value in mojo service manifest.json
// files.
const char kNoSandbox[] = "none";
const char kNetworkSandbox[] = "network";
const char kPpapiSandbox[] = "ppapi";
const char kUtilitySandbox[] = "utility";
const char kWidevineSandbox[] = "widevine";
} // namespace
void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
SandboxType sandbox_type) {
switch (sandbox_type) {
......@@ -25,22 +37,36 @@ void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
switches::kUtilityProcess);
DCHECK(!command_line->HasSwitch(switches::kUtilityProcessSandboxType));
command_line->AppendSwitchASCII(switches::kUtilityProcessSandboxType,
"utility");
kUtilitySandbox);
break;
case SANDBOX_TYPE_GPU:
DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
switches::kGpuProcess);
break;
case SANDBOX_TYPE_PPAPI:
DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
switches::kPpapiPluginProcess);
if (command_line->GetSwitchValueASCII(switches::kProcessType) ==
switches::kUtilityProcess) {
command_line->AppendSwitchASCII(switches::kUtilityProcessSandboxType,
kPpapiSandbox);
} else {
DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
switches::kPpapiPluginProcess);
}
break;
case SANDBOX_TYPE_NETWORK:
DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
switches::kUtilityProcess);
DCHECK(!command_line->HasSwitch(switches::kUtilityProcessSandboxType));
command_line->AppendSwitchASCII(switches::kUtilityProcessSandboxType,
"network");
kNetworkSandbox);
break;
case SANDBOX_TYPE_WIDEVINE:
DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
switches::kUtilityProcess);
DCHECK(!command_line->HasSwitch(switches::kUtilityProcessSandboxType));
command_line->AppendSwitchASCII(switches::kUtilityProcessSandboxType,
kWidevineSandbox);
break;
default:
break;
}
......@@ -80,10 +106,14 @@ SandboxType SandboxTypeFromCommandLine(const base::CommandLine& command_line) {
}
SandboxType UtilitySandboxTypeFromString(const std::string& sandbox_string) {
if (sandbox_string == "none")
if (sandbox_string == kNoSandbox)
return SANDBOX_TYPE_NO_SANDBOX;
if (sandbox_string == "network")
if (sandbox_string == kNetworkSandbox)
return SANDBOX_TYPE_NETWORK;
if (sandbox_string == kPpapiSandbox)
return SANDBOX_TYPE_PPAPI;
if (sandbox_string == kWidevineSandbox)
return SANDBOX_TYPE_WIDEVINE;
return SANDBOX_TYPE_UTILITY;
}
......
......@@ -37,9 +37,12 @@ enum SandboxType {
// The PPAPI plugin process.
SANDBOX_TYPE_PPAPI,
// The network process.
// The network service process.
SANDBOX_TYPE_NETWORK,
// The CDM service process.
SANDBOX_TYPE_WIDEVINE,
SANDBOX_TYPE_AFTER_LAST_TYPE, // Placeholder to ease iteration.
};
......
......@@ -50,13 +50,21 @@ TEST(SandboxTypeTest, Utility) {
EXPECT_EQ(SANDBOX_TYPE_NETWORK, SandboxTypeFromCommandLine(command_line2));
base::CommandLine command_line3(command_line);
SetCommandLineFlagsForSandboxType(&command_line3, SANDBOX_TYPE_NO_SANDBOX);
EXPECT_EQ(SANDBOX_TYPE_NO_SANDBOX, SandboxTypeFromCommandLine(command_line3));
SetCommandLineFlagsForSandboxType(&command_line3, SANDBOX_TYPE_WIDEVINE);
EXPECT_EQ(SANDBOX_TYPE_WIDEVINE, SandboxTypeFromCommandLine(command_line3));
base::CommandLine command_line4(command_line);
command_line4.AppendSwitchASCII(switches::kUtilityProcessSandboxType,
SetCommandLineFlagsForSandboxType(&command_line4, SANDBOX_TYPE_NO_SANDBOX);
EXPECT_EQ(SANDBOX_TYPE_NO_SANDBOX, SandboxTypeFromCommandLine(command_line4));
base::CommandLine command_line5(command_line);
SetCommandLineFlagsForSandboxType(&command_line5, SANDBOX_TYPE_PPAPI);
EXPECT_EQ(SANDBOX_TYPE_PPAPI, SandboxTypeFromCommandLine(command_line5));
base::CommandLine command_line6(command_line);
command_line6.AppendSwitchASCII(switches::kUtilityProcessSandboxType,
"bogus");
EXPECT_EQ(SANDBOX_TYPE_UTILITY, SandboxTypeFromCommandLine(command_line4));
EXPECT_EQ(SANDBOX_TYPE_UTILITY, SandboxTypeFromCommandLine(command_line6));
command_line.AppendSwitch(switches::kNoSandbox);
EXPECT_EQ(SANDBOX_TYPE_NO_SANDBOX, SandboxTypeFromCommandLine(command_line));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment