0

Implement sandbox policy for Video Effects Service on Linux

Changes:
- Introduce pre-sandbox hook for VES that preloads required shared
  library.
- Make VES use the unsandboxed zygote.

Originally authored by mfoltz@ at https://crrev.com/c/5880160.

Bug: 361128453
Change-Id: I69c2bb284c72eb1fb7719b39574f155277fdff2a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5891169
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Reviewed-by: Matthew Denton <mpdenton@chromium.org>
Reviewed-by: Clark DuVall <cduvall@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Commit-Queue: Piotr Bialecki <bialpio@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1361926}
This commit is contained in:
Piotr Bialecki
2024-09-30 18:40:01 +00:00
committed by Chromium LUCI CQ
parent 0beaed2206
commit 9c7e4439d9
11 changed files with 104 additions and 27 deletions

@@ -54,12 +54,6 @@ std::vector<Sandbox> GetSandboxTypesToTest() {
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
if (t == Sandbox::kZygoteIntermediateSandbox) if (t == Sandbox::kZygoteIntermediateSandbox)
continue; continue;
#endif
#if BUILDFLAG(IS_LINUX)
// TODO(crbug.com/361128453): Implement
if (t == Sandbox::kVideoEffects) {
continue;
}
#endif #endif
types.push_back(t); types.push_back(t);
} }
@@ -150,6 +144,9 @@ class UtilityProcessSandboxBrowserTest
#endif #endif
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
case Sandbox::kScreenAI: case Sandbox::kScreenAI:
#endif
#if BUILDFLAG(IS_LINUX)
case Sandbox::kVideoEffects:
#endif #endif
case Sandbox::kSpeechRecognition: { case Sandbox::kSpeechRecognition: {
constexpr int kExpectedPartialSandboxFlags = constexpr int kExpectedPartialSandboxFlags =
@@ -161,9 +158,6 @@ class UtilityProcessSandboxBrowserTest
case Sandbox::kGpu: case Sandbox::kGpu:
case Sandbox::kRenderer: case Sandbox::kRenderer:
#if BUILDFLAG(IS_LINUX)
case Sandbox::kVideoEffects:
#endif
case Sandbox::kZygoteIntermediateSandbox: case Sandbox::kZygoteIntermediateSandbox:
NOTREACHED_IN_MIGRATION(); NOTREACHED_IN_MIGRATION();
break; break;

@@ -163,6 +163,9 @@ ZygoteCommunication* UtilitySandboxedProcessLauncherDelegate::GetZygote() {
#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
sandbox_type_ == sandbox::mojom::Sandbox::kScreenAI || sandbox_type_ == sandbox::mojom::Sandbox::kScreenAI ||
#endif #endif
#if BUILDFLAG(IS_LINUX)
sandbox_type_ == sandbox::mojom::Sandbox::kVideoEffects ||
#endif // BUILDFLAG(IS_LINUX)
sandbox_type_ == sandbox::mojom::Sandbox::kSpeechRecognition) { sandbox_type_ == sandbox::mojom::Sandbox::kSpeechRecognition) {
return GetUnsandboxedZygote(); return GetUnsandboxedZygote();
} }

@@ -81,6 +81,9 @@ source_set("utility") {
if (enable_video_effects) { if (enable_video_effects) {
deps += [ "//services/video_effects:service" ] deps += [ "//services/video_effects:service" ]
if (is_linux) {
deps += [ "//services/video_effects:sandbox_hook" ]
}
} }
# When library CDMs are supported, we support running the CDM in the utility # When library CDMs are supported, we support running the CDM in the utility

@@ -35,6 +35,7 @@
#include "services/on_device_model/on_device_model_service.h" #include "services/on_device_model/on_device_model_service.h"
#include "services/screen_ai/buildflags/buildflags.h" #include "services/screen_ai/buildflags/buildflags.h"
#include "services/tracing/public/cpp/trace_startup.h" #include "services/tracing/public/cpp/trace_startup.h"
#include "services/video_effects/public/cpp/buildflags.h"
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "base/file_descriptor_store.h" #include "base/file_descriptor_store.h"
@@ -62,6 +63,10 @@
#include "media/gpu/sandbox/hardware_video_decoding_sandbox_hook_linux.h" #include "media/gpu/sandbox/hardware_video_decoding_sandbox_hook_linux.h"
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH) #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
#if BUILDFLAG(ENABLE_VIDEO_EFFECTS) && BUILDFLAG(IS_LINUX)
#include "services/video_effects/video_effects_sandbox_hook_linux.h" // nogncheck
#endif // BUILDFLAG(ENABLE_VIDEO_EFFECTS) && BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ash/components/assistant/buildflags.h" #include "chromeos/ash/components/assistant/buildflags.h"
#include "chromeos/ash/services/ime/ime_sandbox_hook.h" #include "chromeos/ash/services/ime/ime_sandbox_hook.h"
@@ -292,11 +297,14 @@ int UtilityMain(MainFunctionParams parameters) {
screen_ai::GetBinaryPathSwitch())); screen_ai::GetBinaryPathSwitch()));
break; break;
#endif #endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kVideoEffects: case sandbox::mojom::Sandbox::kVideoEffects:
// TODO(crbug.com/361128453): Implement this. #if BUILDFLAG(ENABLE_VIDEO_EFFECTS)
NOTREACHED() << "kVideoEffects sandbox not implemented."; pre_sandbox_hook =
#endif base::BindOnce(&video_effects::VideoEffectsPreSandboxHook);
#endif // BUILDFLAG(ENABLE_VIDEO_EFFECTS)
break;
#endif // BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
case sandbox::mojom::Sandbox::kHardwareVideoDecoding: case sandbox::mojom::Sandbox::kHardwareVideoDecoding:
pre_sandbox_hook = pre_sandbox_hook =

@@ -220,9 +220,8 @@ std::unique_ptr<BPFBasePolicy> SandboxSeccompBPF::PolicyForSandboxType(
#endif #endif
#if BUILDFLAG(IS_LINUX) #if BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kVideoEffects: case sandbox::mojom::Sandbox::kVideoEffects:
// TODO(crbug.com/361128453): Implement this. return std::make_unique<ServiceProcessPolicy>();
NOTREACHED() << "kVideoEffects sandbox not implemented."; #endif // BUILDFLAG(IS_LINUX)
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
case sandbox::mojom::Sandbox::kHardwareVideoDecoding: case sandbox::mojom::Sandbox::kHardwareVideoDecoding:
return std::make_unique<HardwareVideoDecodingProcessPolicy>( return std::make_unique<HardwareVideoDecodingProcessPolicy>(
@@ -291,11 +290,6 @@ void SandboxSeccompBPF::RunSandboxSanityChecks(
CHECK_EQ(EPERM, errno); CHECK_EQ(EPERM, errno);
#endif // !defined(NDEBUG) #endif // !defined(NDEBUG)
} break; } break;
#if BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kVideoEffects:
// TODO(crbug.com/361128453): Implement this.
NOTREACHED() << "kVideoEffects sandbox not implemented.";
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
case sandbox::mojom::Sandbox::kHardwareVideoDecoding: case sandbox::mojom::Sandbox::kHardwareVideoDecoding:
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH) #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
@@ -312,6 +306,9 @@ void SandboxSeccompBPF::RunSandboxSanityChecks(
case sandbox::mojom::Sandbox::kScreenAI: case sandbox::mojom::Sandbox::kScreenAI:
#endif #endif
case sandbox::mojom::Sandbox::kAudio: case sandbox::mojom::Sandbox::kAudio:
#if BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kVideoEffects:
#endif // BUILDFLAG(IS_LINUX)
case sandbox::mojom::Sandbox::kService: case sandbox::mojom::Sandbox::kService:
case sandbox::mojom::Sandbox::kServiceWithJit: case sandbox::mojom::Sandbox::kServiceWithJit:
case sandbox::mojom::Sandbox::kSpeechRecognition: case sandbox::mojom::Sandbox::kSpeechRecognition:

@@ -2,8 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import("//services/video_effects/args.gni")
import("//third_party/mediapipe/features.gni") import("//third_party/mediapipe/features.gni")
assert(enable_video_effects,
"The Video Effects service requires enable_video_effects to be true.")
source_set("service") { source_set("service") {
public = [ public = [
"video_effects_processor_impl.h", "video_effects_processor_impl.h",
@@ -43,6 +47,18 @@ source_set("service") {
} }
} }
if (is_linux) {
source_set("sandbox_hook") {
public = [ "video_effects_sandbox_hook_linux.h" ]
sources = [ "video_effects_sandbox_hook_linux.cc" ]
deps = [
"//sandbox/linux:sandbox",
"//sandbox/policy",
"//services/on_device_model/ml:ml_no_internal",
]
}
}
source_set("tests") { source_set("tests") {
testonly = true testonly = true

@@ -8,6 +8,7 @@ include_rules = [
"+gpu/webgpu", "+gpu/webgpu",
"+media/base", "+media/base",
"+media/capture/mojom", "+media/capture/mojom",
"+services/on_device_model/ml/chrome_ml.h",
"+services/viz/public/cpp/gpu", "+services/viz/public/cpp/gpu",
"+services/viz/public/mojom", "+services/viz/public/mojom",
"+services/video_effects/public/mojom", "+services/video_effects/public/mojom",
@@ -27,5 +28,8 @@ specific_include_rules = {
# Included within #if MEDIAPIPE_USE_WEBGPU. # Included within #if MEDIAPIPE_USE_WEBGPU.
"+third_party/mediapipe/src/mediapipe/gpu/webgpu/webgpu_device_registration.h" "+third_party/mediapipe/src/mediapipe/gpu/webgpu/webgpu_device_registration.h"
], ],
"video_effects_sandbox_hook_linux\.[cc|h]": [
"+sandbox/linux",
"+sandbox/policy/linux",
]
} }

@@ -5,3 +5,6 @@ bryantchandler@chromium.org
# Secondary reviewers (use if primary reviewer is unavailable): # Secondary reviewers (use if primary reviewer is unavailable):
ahmedmoussa@google.com ahmedmoussa@google.com
mfoltz@chromium.org mfoltz@chromium.org
per-file video_effects_sandbox_hook_linux.*=set noparent
per-file video_effects_sandbox_hook_linux.*=file://sandbox/linux/OWNERS

@@ -1,5 +0,0 @@
# Running Video Effects Service
Currently, due to incomplete implementation of sandboxing policy for
`Sandbox::kVideoEffects`, running Video Effects Service on MacOS and Linux
requires running Chrome w/ `--no-sandbox` command line switch.

@@ -0,0 +1,37 @@
// 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 "services/video_effects/video_effects_sandbox_hook_linux.h"
#include <dlfcn.h>
#include "sandbox/policy/linux/sandbox_linux.h"
#include "services/on_device_model/ml/chrome_ml.h"
namespace video_effects {
bool VideoEffectsPreSandboxHook(
sandbox::policy::SandboxLinux::Options options) {
// Ensure the optimization_guide_internal shared library is loaded before the
// sandbox is initialized.
const auto path = ml::GetChromeMLPath();
// We don't want to unload the library so not using `ChromeMLHolder` here.
void* ml =
dlopen(path.value().c_str(), RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
if (!ml) {
// The library may be missing on developer builds, we should tolerate that.
// The features in Video Effects Service that require the library will not
// be usable, but we should gracefully handle failures there as well.
LOG(ERROR) << "Failed to open Chrome ML shared library!";
} else {
DVLOG(1) << "Successfully opened Chrome ML shared library.";
}
auto* instance = sandbox::policy::SandboxLinux::GetInstance();
instance->EngageNamespaceSandboxIfPossible();
return true;
}
} // namespace video_effects

@@ -0,0 +1,17 @@
// 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 SERVICES_VIDEO_EFFECTS_VIDEO_EFFECTS_SANDBOX_HOOK_LINUX_H_
#define SERVICES_VIDEO_EFFECTS_VIDEO_EFFECTS_SANDBOX_HOOK_LINUX_H_
#include "sandbox/policy/linux/sandbox_linux.h"
namespace video_effects {
// Loads the Chrome ML (optimization_guide_internal.so) library.
bool VideoEffectsPreSandboxHook(sandbox::policy::SandboxLinux::Options options);
} // namespace video_effects
#endif // SERVICES_VIDEO_EFFECTS_VIDEO_EFFECTS_SANDBOX_HOOK_LINUX_H_