Commit f7d5dc06 authored by evliu's avatar evliu Committed by Commit Bot

Add linux pre hook for the SODA sandbox

This CL adds a pre hook for the SODA sandbox that dlopens the libsoda.so
and grants the necessary broker file permissions required by the speech
recognition library.

Bug: 1039824
Change-Id: I8999cec6b6e8c29b7fbe4dc47dff2b971a6e963d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1995953Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarMatthew Denton <mpdenton@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Commit-Queue: Evan Liu <evliu@google.com>
Cr-Commit-Position: refs/heads/master@{#734061}
parent e2ba4e74
......@@ -89,7 +89,8 @@ class UtilitySandboxedProcessLauncherDelegate
#if defined(OS_CHROMEOS)
sandbox_type_ == service_manager::SandboxType::kIme ||
#endif // OS_CHROMEOS
sandbox_type_ == service_manager::SandboxType::kAudio;
sandbox_type_ == service_manager::SandboxType::kAudio ||
sandbox_type_ == service_manager::SandboxType::kSoda;
DCHECK(supported_sandbox_type);
#endif // DCHECK_IS_ON()
}
......@@ -173,7 +174,8 @@ class UtilitySandboxedProcessLauncherDelegate
#if defined(OS_CHROMEOS)
sandbox_type_ == service_manager::SandboxType::kIme ||
#endif // OS_CHROMEOS
sandbox_type_ == service_manager::SandboxType::kAudio) {
sandbox_type_ == service_manager::SandboxType::kAudio ||
sandbox_type_ == service_manager::SandboxType::kSoda) {
return nullptr;
}
return service_manager::GetGenericZygote();
......
......@@ -77,6 +77,10 @@ jumbo_source_set("utility") {
if (!is_android) {
deps += [ "//services/proxy_resolver:lib" ]
}
if (is_linux) {
deps += [ "//content/utility/soda:soda_sandbox_hook" ]
}
}
# See comment at the top of //content/BUILD.gn for how this works.
......
# Copyright 2020 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.
source_set("soda_sandbox_hook") {
sources = [
"soda_sandbox_hook_linux.cc",
"soda_sandbox_hook_linux.h",
]
deps = [
"//base",
"//components/component_updater:component_updater",
"//sandbox/linux:sandbox_services",
]
public_deps = [ "//services/service_manager/sandbox" ]
}
include_rules = [
"+components/component_updater/component_updater_paths.h",
"+sandbox",
"+services/service_manager/sandbox",
]
per-file soda_sandbox_hook_linux.*=file://sandbox/linux/OWNERS
# COMPONENT: Internals>Sandbox
// Copyright 2020 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/utility/soda/soda_sandbox_hook_linux.h"
#include <dlfcn.h>
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "components/component_updater/component_updater_paths.h"
#include "sandbox/linux/syscall_broker/broker_command.h"
#include "sandbox/linux/syscall_broker/broker_file_permission.h"
using sandbox::syscall_broker::BrokerFilePermission;
using sandbox::syscall_broker::MakeBrokerCommandSet;
namespace soda {
namespace {
constexpr base::FilePath::CharType kSodaDirName[] = FILE_PATH_LITERAL("SODA/");
constexpr base::FilePath::CharType kSodaBinaryFileName[] =
FILE_PATH_LITERAL("SODAFiles/libsoda.so");
std::vector<BrokerFilePermission> GetSodaFilePermissions(
base::FilePath latest_version_dir) {
std::vector<BrokerFilePermission> permissions{
BrokerFilePermission::ReadOnly("/dev/urandom"),
BrokerFilePermission::ReadOnlyRecursive(
latest_version_dir.AsEndingWithSeparator().value())};
return permissions;
}
} // namespace
bool SodaPreSandboxHook(service_manager::SandboxLinux::Options options) {
base::FilePath components_dir;
base::PathService::Get(component_updater::DIR_COMPONENT_USER,
&components_dir);
// Get the directory containing the latest version of SODA. In most cases
// there will only be one version of SODA, but it is possible for there to be
// multiple versions if a newer version of SODA was recently downloaded before
// the old version gets cleaned up.
base::FileEnumerator enumerator(components_dir.Append(kSodaDirName), false,
base::FileEnumerator::DIRECTORIES);
base::FilePath latest_version_dir;
for (base::FilePath version_dir = enumerator.Next(); !version_dir.empty();
version_dir = enumerator.Next()) {
latest_version_dir =
latest_version_dir < version_dir ? version_dir : latest_version_dir;
}
void* soda_library =
latest_version_dir.empty()
? nullptr
: dlopen(
latest_version_dir.Append(kSodaBinaryFileName).value().c_str(),
RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
DCHECK(soda_library);
auto* instance = service_manager::SandboxLinux::GetInstance();
instance->StartBrokerProcess(MakeBrokerCommandSet({
sandbox::syscall_broker::COMMAND_ACCESS,
sandbox::syscall_broker::COMMAND_OPEN,
sandbox::syscall_broker::COMMAND_READLINK,
sandbox::syscall_broker::COMMAND_STAT,
}),
GetSodaFilePermissions(latest_version_dir),
service_manager::SandboxLinux::PreSandboxHook(),
options);
instance->EngageNamespaceSandboxIfPossible();
return true;
}
} // namespace soda
// Copyright 2020 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_UTILITY_SODA_SODA_SANDBOX_HOOK_LINUX_H_
#define CONTENT_UTILITY_SODA_SODA_SANDBOX_HOOK_LINUX_H_
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
namespace soda {
// Opens the libsoda.so binary and grants broker file permissions to the
// necessary files required by the binary.
bool SodaPreSandboxHook(service_manager::SandboxLinux::Options options);
} // namespace soda
#endif // CONTENT_UTILITY_SODA_SODA_SANDBOX_HOOK_LINUX_H_
......@@ -22,6 +22,7 @@
#include "services/service_manager/sandbox/sandbox.h"
#if defined(OS_LINUX)
#include "content/utility/soda/soda_sandbox_hook_linux.h"
#include "services/audio/audio_sandbox_hook_linux.h"
#include "services/network/network_sandbox_hook_linux.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
......@@ -82,12 +83,15 @@ int UtilityMain(const MainFunctionParams& parameters) {
#if defined(OS_CHROMEOS)
sandbox_type == service_manager::SandboxType::kIme ||
#endif // OS_CHROMEOS
sandbox_type == service_manager::SandboxType::kAudio) {
sandbox_type == service_manager::SandboxType::kAudio ||
sandbox_type == service_manager::SandboxType::kSoda) {
service_manager::SandboxLinux::PreSandboxHook pre_sandbox_hook;
if (sandbox_type == service_manager::SandboxType::kNetwork)
pre_sandbox_hook = base::BindOnce(&network::NetworkPreSandboxHook);
else if (sandbox_type == service_manager::SandboxType::kAudio)
pre_sandbox_hook = base::BindOnce(&audio::AudioPreSandboxHook);
else if (sandbox_type == service_manager::SandboxType::kSoda)
pre_sandbox_hook = base::BindOnce(&soda::SodaPreSandboxHook);
#if defined(OS_CHROMEOS)
else if (sandbox_type == service_manager::SandboxType::kIme)
pre_sandbox_hook = base::BindOnce(&chromeos::ime::ImePreSandboxHook);
......
......@@ -4,18 +4,12 @@
#include "services/service_manager/sandbox/linux/bpf_soda_policy_linux.h"
#include <sys/socket.h>
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/syscall_broker/broker_process.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "services/service_manager/sandbox/linux/sandbox_linux.h"
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::ResultExpr;
using sandbox::bpf_dsl::Trap;
using sandbox::syscall_broker::BrokerProcess;
......@@ -27,36 +21,9 @@ SodaProcessPolicy::~SodaProcessPolicy() = default;
ResultExpr SodaProcessPolicy::EvaluateSyscall(int system_call_number) const {
switch (system_call_number) {
#if defined(__NR_uname)
case __NR_uname:
#endif
#if defined(__NR_setitimer)
case __NR_setitimer:
#endif
#if defined(__NR_sigaltstack)
case __NR_sigaltstack:
#endif
#if defined(__NR_eventfd2)
case __NR_eventfd2:
#endif
#if defined(__NR_getitimer)
case __NR_getitimer:
#endif
#if defined(__NR_rseq)
case __NR_rseq:
#endif
return Allow();
#if defined(__NR_prlimit64)
case __NR_prlimit64:
return sandbox::RestrictPrlimit64(GetPolicyPid());
#endif
#if defined(__NR_getsockopt)
case __NR_getsockopt: {
const Arg<int> level(1);
const Arg<int> optname(2);
return If(AllOf(level == SOL_SOCKET, optname == SO_PEEK_OFF), Allow())
.Else(sandbox::CrashSIGSYS());
}
#endif
default:
auto* broker_process = SandboxLinux::GetInstance()->broker_process();
......
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