0

Implement sandbox for OnDeviceTranslation service on Linux

This CL implements sandboxing for OnDeviceTranslation service on Linux.

We allow `membarrier` syscall and reading
"/sys/devices/system/cpu/possible" inside the sandboxed
OnDeviceTranslation service process.

Note: The sandboxed OnDeviceTranslation service will crash until
https://crbug.com/369491267 is resolved.

Bug: 340778819
Change-Id: I289294f35d55bb5dad6bcc0fba422b4077ae2ae7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884817
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Matthew Denton <mpdenton@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1362827}
This commit is contained in:
Tsuyoshi Horo
2024-10-02 03:40:14 +00:00
committed by Chromium LUCI CQ
parent f40d5a6605
commit c640242894
20 changed files with 201 additions and 14 deletions

@ -22,6 +22,15 @@ source_set("on_device_translation_service") {
"//components/services/on_device_translation/public/mojom",
"//mojo/public/cpp/bindings",
]
if (is_linux) {
sources += [
"sandbox_hook.cc",
"sandbox_hook.h",
]
deps += [ "//sandbox/linux:sandbox_services" ]
public_deps += [ "//sandbox/policy" ]
}
}
source_set("unit_tests") {

@ -0,0 +1,8 @@
specific_include_rules = {
"sandbox_hook\.cc": [
"+sandbox/linux/syscall_broker/broker_command.h",
],
"sandbox_hook\.h": [
"+sandbox/policy/linux/sandbox_linux.h",
],
}

@ -1 +1,4 @@
file://chrome/browser/ai/OWNERS
per-file sandbox_hook.*=set noparent
per-file sandbox_hook.*=file://sandbox/linux/OWNERS

@ -13,4 +13,8 @@ mojom("mojom") {
"//mojo/public/mojom/base",
"//sandbox/policy/mojom",
]
enabled_features = []
if (is_linux || is_mac) {
enabled_features += [ "is_linux_or_mac" ]
}
}

@ -42,12 +42,12 @@ struct OnDeviceTranslationServiceConfig {
// Currently the sandboxing of the On Device Translation service is supported
// only on macOS.
// only on macOS and Linux.
// TODO(crbug.com/340778819): Implement sandboxing on other platforms.
[EnableIf=is_mac]
[EnableIf=is_linux_or_mac]
const sandbox.mojom.Sandbox kOnDeviceTranslationSandbox
= sandbox.mojom.Sandbox.kOnDeviceTranslation;
[EnableIfNot=is_mac]
[EnableIfNot=is_linux_or_mac]
const sandbox.mojom.Sandbox kOnDeviceTranslationSandbox
= sandbox.mojom.Sandbox.kNoSandbox;

@ -0,0 +1,43 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/services/on_device_translation/sandbox_hook.h"
#include "components/services/on_device_translation/translate_kit_client.h"
#include "sandbox/linux/syscall_broker/broker_command.h"
using sandbox::syscall_broker::BrokerFilePermission;
using sandbox::syscall_broker::MakeBrokerCommandSet;
namespace on_device_translation {
namespace {
// Gets the file permissions required by the TranslateKit
std::vector<BrokerFilePermission> GetOnDeviceTranslationFilePermissions() {
std::vector<BrokerFilePermission> permissions{
// Opened for checking the CPU numbers.
BrokerFilePermission::ReadOnly("/sys/devices/system/cpu/possible"),
};
return permissions;
}
} // namespace
bool OnDeviceTranslationSandboxHook(
sandbox::policy::SandboxLinux::Options options) {
// Call `TranslateKitClient::Get()` to load libtranslatekit.so
TranslateKitClient::Get();
auto* instance = sandbox::policy::SandboxLinux::GetInstance();
instance->StartBrokerProcess(MakeBrokerCommandSet({
sandbox::syscall_broker::COMMAND_OPEN,
}),
GetOnDeviceTranslationFilePermissions(),
options);
instance->EngageNamespaceSandboxIfPossible();
return true;
}
} // namespace on_device_translation

@ -0,0 +1,19 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SERVICES_ON_DEVICE_TRANSLATION_SANDBOX_HOOK_H_
#define COMPONENTS_SERVICES_ON_DEVICE_TRANSLATION_SANDBOX_HOOK_H_
#include "sandbox/policy/linux/sandbox_linux.h"
namespace on_device_translation {
// Opens the TranslateKit binary and grants broker file permissions to the
// necessary files required by the binary.
bool OnDeviceTranslationSandboxHook(
sandbox::policy::SandboxLinux::Options options);
} // namespace on_device_translation
#endif // COMPONENTS_SERVICES_ON_DEVICE_TRANSLATION_SANDBOX_HOOK_H_

@ -147,6 +147,7 @@ class UtilityProcessSandboxBrowserTest
#endif
#if BUILDFLAG(IS_LINUX)
case Sandbox::kVideoEffects:
case Sandbox::kOnDeviceTranslation:
#endif
case Sandbox::kSpeechRecognition: {
constexpr int kExpectedPartialSandboxFlags =

@ -96,7 +96,7 @@ UtilitySandboxedProcessLauncherDelegate::
#if BUILDFLAG(IS_LINUX)
sandbox_type_ == sandbox::mojom::Sandbox::kVideoEffects ||
#endif
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
sandbox_type_ == sandbox::mojom::Sandbox::kOnDeviceTranslation ||
#endif
sandbox_type_ == sandbox::mojom::Sandbox::kAudio ||
@ -165,6 +165,7 @@ ZygoteCommunication* UtilitySandboxedProcessLauncherDelegate::GetZygote() {
#endif
#if BUILDFLAG(IS_LINUX)
sandbox_type_ == sandbox::mojom::Sandbox::kVideoEffects ||
sandbox_type_ == sandbox::mojom::Sandbox::kOnDeviceTranslation ||
#endif // BUILDFLAG(IS_LINUX)
sandbox_type_ == sandbox::mojom::Sandbox::kSpeechRecognition) {
return GetUnsandboxedZygote();

@ -43,6 +43,7 @@ source_set("utility") {
"//build:branding_buildflags",
"//build:chromeos_buildflags",
"//components/optimization_guide/core:features",
"//components/services/on_device_translation:on_device_translation_service",
"//components/services/storage",
"//components/services/storage/public/mojom",
"//content:export",

@ -3,6 +3,7 @@ include_rules = [
"+chromeos/ash/services/ime",
"+components/optimization_guide/core/optimization_guide_features.h",
"+components/services/storage",
"+components/services/on_device_translation",
"+content/child",
"+content/public/utility",
"+content/services",

@ -102,6 +102,9 @@
sandbox::TargetServices* g_utility_target_services = nullptr;
#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_LINUX)
#include "components/services/on_device_translation/sandbox_hook.h"
#endif // BUILDFLAG(IS_LINUX)
namespace content {
namespace {
@ -289,6 +292,12 @@ int UtilityMain(MainFunctionParams parameters) {
pre_sandbox_hook =
base::BindOnce(&speech::SpeechRecognitionPreSandboxHook);
break;
#if BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kOnDeviceTranslation:
pre_sandbox_hook = base::BindOnce(
&on_device_translation::OnDeviceTranslationSandboxHook);
break;
#endif // BUILDFLAG(IS_LINUX)
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
case sandbox::mojom::Sandbox::kScreenAI:
pre_sandbox_hook =

@ -74,6 +74,8 @@ component("policy") {
"linux/bpf_gpu_policy_linux.h",
"linux/bpf_network_policy_linux.cc",
"linux/bpf_network_policy_linux.h",
"linux/bpf_on_device_translation_policy_linux.cc",
"linux/bpf_on_device_translation_policy_linux.h",
"linux/bpf_ppapi_policy_linux.cc",
"linux/bpf_ppapi_policy_linux.h",
"linux/bpf_print_compositor_policy_linux.cc",

@ -0,0 +1,45 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/policy/linux/bpf_on_device_translation_policy_linux.h"
#include <sys/mman.h>
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/policy/linux/sandbox_linux.h"
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::ResultExpr;
namespace sandbox::policy {
namespace {
static constexpr int kMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ = (1 << 8);
}
ResultExpr OnDeviceTranslationProcessPolicy::EvaluateSyscall(
int system_call_number) const {
switch (system_call_number) {
case __NR_membarrier: {
// `membarrier` is used at http://shortn/_d034oISVml (Google-internal).
const Arg<int> cmd(0);
return If(cmd == kMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ, Allow())
.Else(sandbox::CrashSIGSYS());
}
default:
auto* sandbox_linux = SandboxLinux::GetInstance();
if (sandbox_linux->ShouldBrokerHandleSyscall(system_call_number)) {
return sandbox_linux->HandleViaBroker(system_call_number);
}
// Default on the content baseline policy.
return BPFBasePolicy::EvaluateSyscall(system_call_number);
}
}
} // namespace sandbox::policy

@ -0,0 +1,30 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_POLICY_LINUX_BPF_ON_DEVICE_TRANSLATION_POLICY_LINUX_H_
#define SANDBOX_POLICY_LINUX_BPF_ON_DEVICE_TRANSLATION_POLICY_LINUX_H_
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/policy/linux/bpf_base_policy_linux.h"
namespace sandbox::policy {
// This policy is be used by OnDeviceTranslation processe.
class SANDBOX_POLICY_EXPORT OnDeviceTranslationProcessPolicy
: public BPFBasePolicy {
public:
OnDeviceTranslationProcessPolicy() = default;
~OnDeviceTranslationProcessPolicy() override = default;
OnDeviceTranslationProcessPolicy(const OnDeviceTranslationProcessPolicy&) =
delete;
OnDeviceTranslationProcessPolicy& operator=(
const OnDeviceTranslationProcessPolicy&) = delete;
bpf_dsl::ResultExpr EvaluateSyscall(int system_call_number) const override;
};
} // namespace sandbox::policy
#endif // SANDBOX_POLICY_LINUX_BPF_ON_DEVICE_TRANSLATION_POLICY_LINUX_H_

@ -75,6 +75,10 @@
#include "sandbox/policy/linux/bpf_hardware_video_decoding_policy_linux.h"
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
#if BUILDFLAG(IS_LINUX)
#include "sandbox/policy/linux/bpf_on_device_translation_policy_linux.h"
#endif // BUILDFLAG(IS_LINUX)
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::ResultExpr;
@ -214,6 +218,10 @@ std::unique_ptr<BPFBasePolicy> SandboxSeccompBPF::PolicyForSandboxType(
return std::make_unique<ServiceProcessPolicy>();
case sandbox::mojom::Sandbox::kSpeechRecognition:
return std::make_unique<SpeechRecognitionProcessPolicy>();
#if BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kOnDeviceTranslation:
return std::make_unique<OnDeviceTranslationProcessPolicy>();
#endif // BUILDFLAG(IS_LINUX)
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
case sandbox::mojom::Sandbox::kScreenAI:
return std::make_unique<ScreenAIProcessPolicy>();
@ -317,6 +325,9 @@ void SandboxSeccompBPF::RunSandboxSanityChecks(
case sandbox::mojom::Sandbox::kPrintBackend:
#endif
case sandbox::mojom::Sandbox::kOnDeviceModelExecution:
#if BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kOnDeviceTranslation:
#endif // BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kUtility:
case sandbox::mojom::Sandbox::kNoSandbox:
case sandbox::mojom::Sandbox::kZygoteIntermediateSandbox:

@ -168,8 +168,8 @@ enum Sandbox {
// Hosts On Device Translation service.
// Currently the sandboxing of the On Device Translation service is supported
// only on macOS.
// only on macOS and Linux.
// TODO(crbug.com/340778819): Implement sandboxing on other platforms.
[EnableIf=is_mac]
[EnableIf=is_linux_or_mac]
kOnDeviceTranslation,
};

@ -84,7 +84,7 @@ bool IsUnsandboxedSandboxType(Sandbox sandbox_type) {
#if BUILDFLAG(IS_LINUX)
case Sandbox::kVideoEffects:
#endif
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
case Sandbox::kOnDeviceTranslation:
#endif
return false;
@ -171,7 +171,7 @@ void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
#if BUILDFLAG(IS_LINUX)
case Sandbox::kVideoEffects:
#endif
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
case Sandbox::kOnDeviceTranslation:
#endif
DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
@ -285,7 +285,7 @@ std::string StringFromUtilitySandboxType(Sandbox sandbox_type) {
case Sandbox::kVideoEffects:
return switches::kVideoEffectsSandbox;
#endif
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
case Sandbox::kOnDeviceTranslation:
return switches::kOnDeviceTranslationSandbox;
#endif
@ -404,7 +404,7 @@ sandbox::mojom::Sandbox UtilitySandboxTypeFromString(
return Sandbox::kVideoEffects;
}
#endif
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
if (sandbox_string == switches::kOnDeviceTranslationSandbox) {
return Sandbox::kOnDeviceTranslation;
}

@ -71,9 +71,9 @@ const char kLibassistantSandbox[] = "libassistant";
#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
const char kOnDeviceTranslationSandbox[] = "on_device_translation";
#endif // BUILDFLAG(IS_MAC)
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
// Flags owned by the service manager sandbox.

@ -74,9 +74,9 @@ SANDBOX_POLICY_EXPORT extern const char kLibassistantSandbox[];
#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
SANDBOX_POLICY_EXPORT extern const char kOnDeviceTranslationSandbox[];
#endif // BUILDFLAG(IS_MAC)
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
// Flags owned by the service manager sandbox.
SANDBOX_POLICY_EXPORT extern const char kAllowSandboxDebugging[];