#include "media/gpu/sandbox/hardware_video_encoding_sandbox_hook_linux.h"
#include <dlfcn.h>
#include <sys/stat.h>
#include "base/strings/stringprintf.h"
#include "media/gpu/buildflags.h"
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_wrapper.h"
#endif
#if BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/v4l2/v4l2_device.h"
#endif
using sandbox::syscall_broker::BrokerFilePermission;
namespace media {
bool HardwareVideoEncodingPreSandboxHook(
sandbox::policy::SandboxLinux::Options options) {
sandbox::syscall_broker::BrokerCommandSet command_set;
std::vector<BrokerFilePermission> permissions;
#if BUILDFLAG(USE_V4L2_CODEC)
command_set.set(sandbox::syscall_broker::COMMAND_OPEN);
static constexpr size_t MAX_V4L2_ENCODERS = 5;
static const base::FilePath::CharType kVideoEncBase[] = "/dev/video-enc";
permissions.push_back(BrokerFilePermission::ReadWrite(kVideoEncBase));
for (size_t i = 0; i < MAX_V4L2_ENCODERS; i++) {
std::ostringstream encoderPath;
encoderPath << kVideoEncBase << i;
permissions.push_back(BrokerFilePermission::ReadWrite(encoderPath.str()));
}
static const char kDevImageProc0Path[] = "/dev/image-proc0";
permissions.push_back(BrokerFilePermission::ReadWrite(kDevImageProc0Path));
#elif BUILDFLAG(USE_VAAPI)
command_set.set(sandbox::syscall_broker::COMMAND_OPEN);
command_set.set(sandbox::syscall_broker::COMMAND_STAT);
command_set.set(sandbox::syscall_broker::COMMAND_ACCESS);
if (options.use_amd_specific_policies) {
command_set.set(sandbox::syscall_broker::COMMAND_READLINK);
permissions.push_back(BrokerFilePermission::ReadOnly("/dev/dri"));
static const char* kDevices[] = {"/sys/dev/char", "/sys/devices"};
for (const char* item : kDevices) {
std::string path(item);
permissions.push_back(
BrokerFilePermission::StatOnlyWithIntermediateDirs(path));
permissions.push_back(
BrokerFilePermission::ReadOnlyRecursive(path + "/"));
}
permissions.push_back(
BrokerFilePermission::ReadOnly("/usr/share/vulkan/icd.d"));
permissions.push_back(BrokerFilePermission::ReadOnly(
"/usr/share/vulkan/icd.d/radeon_icd.x86_64.json"));
}
#endif
for (int i = 128; i <= 137; ++i) {
const std::string path = base::StringPrintf("/dev/dri/renderD%d", i);
struct stat st;
if (stat(path.c_str(), &st) == 0) {
permissions.push_back(options.use_amd_specific_policies
? BrokerFilePermission::ReadWrite(path)
: BrokerFilePermission::ReadOnly(path));
#if BUILDFLAG(USE_VAAPI)
uint32_t major = (static_cast<uint32_t>(st.st_rdev) >> 8) & 0xff;
uint32_t minor = static_cast<uint32_t>(st.st_rdev) & 0xff;
std::string char_device_path =
base::StringPrintf("/sys/dev/char/%u:%u/", major, minor);
permissions.push_back(
BrokerFilePermission::ReadOnlyRecursive(char_device_path));
#endif
}
}
sandbox::policy::SandboxLinux::GetInstance()->StartBrokerProcess(
command_set, permissions, options);
#if BUILDFLAG(USE_VAAPI)
VaapiWrapper::PreSandboxInitialization(true);
if (options.use_amd_specific_policies) {
constexpr int kDlopenFlags = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE;
const char* radeonsi_lib = "/usr/lib64/dri/radeonsi_dri.so";
#if defined(DRI_DRIVER_DIR)
radeonsi_lib = DRI_DRIVER_DIR "/radeonsi_dri.so";
#endif
if (nullptr == dlopen(radeonsi_lib, kDlopenFlags)) {
LOG(ERROR) << "dlopen(radeonsi_dri.so) failed with error: " << dlerror();
return false;
}
dlopen("libvulkan.so.1", kDlopenFlags);
dlopen("libvulkan_radeon.so", kDlopenFlags);
}
#endif
return true;
}
}