blob: 96801293f3c11819fe2d4f0650a44d3b8875f49e [file] [log] [blame]
// Copyright 2022 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/screen_ai/sandbox/screen_ai_sandbox_hook_linux.h"
#include <dlfcn.h>
#include "base/cpu.h"
#include "base/debug/alias.h"
#include "base/files/file_util.h"
#include "components/crash/core/common/crash_key.h"
#include "sandbox/linux/syscall_broker/broker_command.h"
#include "sandbox/linux/syscall_broker/broker_file_permission.h"
#include "services/screen_ai/buildflags/buildflags.h"
#include "services/screen_ai/public/cpp/utilities.h"
#include "third_party/abseil-cpp/absl/strings/str_format.h"
using sandbox::syscall_broker::BrokerFilePermission;
using sandbox::syscall_broker::MakeBrokerCommandSet;
namespace screen_ai {
namespace {
#if !BUILDFLAG(USE_FAKE_SCREEN_AI)
NO_SANITIZE("cfi-icall")
void CallPresandboxInitFunction(void* presandbox_init_function) {
DCHECK(presandbox_init_function);
typedef void (*PresandboxInitFn)();
(*reinterpret_cast<PresandboxInitFn>(presandbox_init_function))();
}
#endif
} // namespace
bool ScreenAIPreSandboxHook(base::FilePath binary_path,
sandbox::policy::SandboxLinux::Options options) {
if (binary_path.empty()) {
VLOG(0) << "Screen AI component binary not found.";
} else {
// TODO(crbug.com/418199684): Remove after the crash is fixed.
// Add CPU brand name as crash key and the entire CPU info in minidump in
// case details are needed.
base::CPU cpu;
base::debug::Alias(&cpu);
static crash_reporter::CrashKeyString<50> cpu_brand("cpu-brand");
cpu_brand.Set(absl::StrFormat("%.50s", cpu.cpu_brand()));
void* screen_ai_library = dlopen(binary_path.value().c_str(),
RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE);
// The library is delivered by the component updater or DLC. If it is not
// available or has loading or syntax problems, we cannot do anything about
// them here. The requests to the service will fail later as the library
// does not exist or does not initialize.
if (screen_ai_library == nullptr) {
VLOG(0) << dlerror();
binary_path.clear();
} else {
void* presandbox_init = dlsym(screen_ai_library, "PresandboxInit");
if (presandbox_init == nullptr) {
VLOG(0) << "PresandboxInit function of Screen AI library not found.";
binary_path.clear();
} else {
#if !BUILDFLAG(USE_FAKE_SCREEN_AI)
VLOG(2) << "Screen AI library loaded pre-sandboxing: " << binary_path;
CallPresandboxInitFunction(presandbox_init);
#endif
}
}
}
auto* instance = sandbox::policy::SandboxLinux::GetInstance();
std::vector<BrokerFilePermission> permissions{
BrokerFilePermission::ReadOnly("/dev/urandom"),
BrokerFilePermission::ReadOnly("/proc/cpuinfo"),
BrokerFilePermission::ReadOnly("/proc/meminfo"),
BrokerFilePermission::ReadOnly("/sys/devices/system/cpu/possible")};
#if BUILDFLAG(IS_CHROMEOS)
permissions.push_back(BrokerFilePermission::ReadOnly("/proc/self/status"));
permissions.push_back(
BrokerFilePermission::ReadOnly("/sys/devices/system/cpu/kernel_max"));
permissions.push_back(
BrokerFilePermission::ReadOnly("/sys/devices/system/cpu/present"));
#endif
instance->StartBrokerProcess(
MakeBrokerCommandSet({sandbox::syscall_broker::COMMAND_ACCESS,
sandbox::syscall_broker::COMMAND_OPEN}),
permissions, options);
instance->EngageNamespaceSandboxIfPossible();
return true;
}
} // namespace screen_ai