// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/common/gpu_pre_sandbox_hook_linux.h"

#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>

#include <array>
#include <memory>
#include <sstream>
#include <utility>
#include <vector>

#include "base/base_paths.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/scoped_file.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "content/public/common/content_switches.h"
#include "media/gpu/buildflags.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/syscall_broker/broker_command.h"
#include "sandbox/linux/syscall_broker/broker_file_permission.h"
#include "sandbox/linux/syscall_broker/broker_process.h"
#include "sandbox/policy/chromecast_sandbox_allowlist_buildflags.h"
#include "sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.h"
#include "sandbox/policy/linux/bpf_cros_arm_gpu_policy_linux.h"
#include "sandbox/policy/linux/bpf_gpu_policy_linux.h"
#include "sandbox/policy/linux/sandbox_linux.h"

#if BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/v4l2/v4l2_device.h"
#endif

using sandbox::bpf_dsl::Policy;
using sandbox::syscall_broker::BrokerFilePermission;
using sandbox::syscall_broker::BrokerProcess;

namespace content {
namespace {

inline bool IsChromeOS() {
#if BUILDFLAG(IS_CHROMEOS)
  return true;
#else
  return false;
#endif
}

inline bool UseChromecastSandboxAllowlist() {
#if BUILDFLAG(ENABLE_CHROMECAST_GPU_SANDBOX_ALLOWLIST)
  return true;
#else
  return false;
#endif
}

inline bool IsArchitectureArm() {
#if defined(ARCH_CPU_ARM_FAMILY)
  return true;
#else
  return false;
#endif
}

inline bool UseV4L2Codec(
    const sandbox::policy::SandboxSeccompBPF::Options& options) {
#if BUILDFLAG(USE_V4L2_CODEC)
  return options.accelerated_video_decode_enabled ||
      options.accelerated_video_encode_enabled;
#else
  return false;
#endif
}

#if BUILDFLAG(IS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
static const char kMaliConfPath[] = "/etc/mali_platform.conf";
#endif

#if BUILDFLAG(IS_CHROMEOS) && defined(__aarch64__)
static const char kLibGlesPath[] = "/usr/lib64/libGLESv2.so.2";
static const char kLibEglPath[] = "/usr/lib64/libEGL.so.1";
static const char kLibMaliPath[] = "/usr/lib64/libmali.so";
static const char kLibTegraPath[] = "/usr/lib64/libtegrav4l2.so";
#else
static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
static const char kLibMaliPath[] = "/usr/lib/libmali.so";
static const char kLibTegraPath[] = "/usr/lib/libtegrav4l2.so";
#endif

constexpr int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE;

void AddStandardChromeOsPermissions(
    std::vector<BrokerFilePermission>* permissions) {
  // For the ANGLE passthrough command decoder.
  static const char* const kReadOnlyList[] = {"libEGL.so", "libGLESv2.so"};
  for (const char* item : kReadOnlyList) {
    base::FilePath module_dir;
    if (base::PathService::Get(base::DIR_MODULE, &module_dir)) {
      std::string lib_path = module_dir.Append(item).MaybeAsASCII();
      if (!lib_path.empty()) {
        permissions->push_back(BrokerFilePermission::ReadOnly(lib_path));
      }
    }
  }
}

void AddV4L2GpuPermissions(
    std::vector<BrokerFilePermission>* permissions,
    const sandbox::policy::SandboxSeccompBPF::Options& options) {
  if (options.accelerated_video_decode_enabled) {
    // Device nodes for V4L2 video decode accelerator drivers.
    // We do not use a FileEnumerator because the device files may not exist
    // yet when the sandbox is created. But since we are restricting access
    // to the video-dec* and media-dec* prefixes we know that we cannot
    // authorize a non-decoder device by accident.
    static constexpr size_t MAX_V4L2_DECODERS = 5;
    static const base::FilePath::CharType kDevicePath[] =
        FILE_PATH_LITERAL("/dev/");
    static const base::FilePath::CharType kVideoDecBase[] = "video-dec";
    static const base::FilePath::CharType kMediaDecBase[] = "media-dec";
    for (size_t i = 0; i < MAX_V4L2_DECODERS; i++) {
      std::ostringstream decoderPath;
      decoderPath << kDevicePath << kVideoDecBase << i;
      permissions->push_back(
          BrokerFilePermission::ReadWrite(decoderPath.str()));

      std::ostringstream mediaDevicePath;
      mediaDevicePath << kDevicePath << kMediaDecBase << i;
      permissions->push_back(
          BrokerFilePermission::ReadWrite(mediaDevicePath.str()));
    }
  }

  // Image processor used on ARM platforms.
  static const char kDevImageProc0Path[] = "/dev/image-proc0";
  permissions->push_back(BrokerFilePermission::ReadWrite(kDevImageProc0Path));

  if (options.accelerated_video_encode_enabled) {
    // Device node for V4L2 video encode accelerator drivers.
    // See comments above for why we don't use a FileEnumerator.
    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()));
    }
  }

  // Device node for V4L2 JPEG decode accelerator drivers.
  static const char kDevJpegDecPath[] = "/dev/jpeg-dec";
  permissions->push_back(BrokerFilePermission::ReadWrite(kDevJpegDecPath));

  // Device node for V4L2 JPEG encode accelerator drivers.
  static const char kDevJpegEncPath[] = "/dev/jpeg-enc";
  permissions->push_back(BrokerFilePermission::ReadWrite(kDevJpegEncPath));

  // Additional device nodes for V4L2 JPEG decode encode accelerator drivers,
  // as ChromeOS can have both /dev/jpeg-dec and /dev/jpeg-decN naming styles.
  // See comments above for why we don't use a FileEnumerator.
  static constexpr size_t MAX_V4L2_JPEG_NODES = 5;
  for (size_t i = 0; i < MAX_V4L2_JPEG_NODES; i++) {
    std::ostringstream jpegDecPath;
    jpegDecPath << kDevJpegDecPath << i;
    permissions->push_back(
        BrokerFilePermission::ReadWrite(jpegDecPath.str()));

    std::ostringstream jpegEncPath;
    jpegEncPath << kDevJpegEncPath << i;
    permissions->push_back(
        BrokerFilePermission::ReadWrite(jpegEncPath.str()));
  }

  if (UseChromecastSandboxAllowlist()) {
    static const char kAmlogicAvcEncoderPath[] = "/dev/amvenc_avc";
    permissions->push_back(
        BrokerFilePermission::ReadWrite(kAmlogicAvcEncoderPath));
  }
}

void AddArmMaliGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  // Device file needed by the ARM GPU userspace.
  static const char kMali0Path[] = "/dev/mali0";

  permissions->push_back(BrokerFilePermission::ReadWrite(kMali0Path));
  // Need to be able to dlopen libmali.so from libEGL.so.
  permissions->push_back(BrokerFilePermission::ReadOnly(kLibMaliPath));

#if BUILDFLAG(IS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
  // Files needed for protected DMA allocations.
  static const char kDmaHeapPath[] = "/dev/dma_heap/restricted_mtk_cma";
  permissions->push_back(BrokerFilePermission::ReadWrite(kDmaHeapPath));
  permissions->push_back(BrokerFilePermission::ReadOnly(kMaliConfPath));
#endif

  // Non-privileged render nodes for format enumeration.
  // https://dri.freedesktop.org/docs/drm/gpu/drm-uapi.html#render-nodes
  base::FileEnumerator enumerator(
      base::FilePath(FILE_PATH_LITERAL("/dev/dri/")), false /* recursive */,
      base::FileEnumerator::FILES, FILE_PATH_LITERAL("renderD*"));
  for (base::FilePath name = enumerator.Next(); !name.empty();
       name = enumerator.Next()) {
    permissions->push_back(BrokerFilePermission::ReadWrite(name.value()));
  }
}

void AddImgPvrGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  // Device node needed by the IMG GPU userspace.
  static const char kPvrSyncPath[] = "/dev/pvr_sync";

  permissions->push_back(BrokerFilePermission::ReadWrite(kPvrSyncPath));
}

void AddDrmGpuDevPermissions(std::vector<BrokerFilePermission>* permissions,
                             const std::string& path) {
  struct stat st;

  if (stat(path.c_str(), &st) == 0) {
    permissions->push_back(BrokerFilePermission::ReadWrite(path));

    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));
  }
}

void AddDrmGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  permissions->push_back(BrokerFilePermission::ReadOnly("/dev/dri"));
  for (int i = 0; i <= 9; ++i) {
    AddDrmGpuDevPermissions(permissions,
                            base::StringPrintf("/dev/dri/card%d", i));
    AddDrmGpuDevPermissions(permissions,
                            base::StringPrintf("/dev/dri/renderD%d", i + 128));
  }
}

void AddAmdGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  static const char* const kReadOnlyList[] = {
      "/etc/ld.so.cache",
      // To support threads in mesa we use --gpu-sandbox-start-early and
      // that requires the following libs and files to be accessible.
      "/usr/lib64/libEGL.so.1",
      "/usr/lib64/libGLESv2.so.2",
      "/usr/lib64/libglapi.so.0",
      "/usr/lib64/libgallium_dri.so",
      "/usr/lib64/dri/r300_dri.so",
      "/usr/lib64/dri/r600_dri.so",
      "/usr/lib64/dri/radeonsi_dri.so",
      // Allow libglvnd files and libs.
      "/usr/share/glvnd/egl_vendor.d",
      "/usr/share/glvnd/egl_vendor.d/50_mesa.json",
      "/usr/lib64/libEGL_mesa.so.0",
      "/usr/lib64/libGLdispatch.so.0"};
  for (const char* item : kReadOnlyList)
    permissions->push_back(BrokerFilePermission::ReadOnly(item));

  AddDrmGpuPermissions(permissions);

  // NOTE: control nodes are probably not required:
  // NOTE: amdgpu.ids should probably be read-only:
  static const char* const kReadWriteList[] = {
      "/dev/dri/controlD64",
      "/sys/class/drm/card0/device/config",
      "/sys/class/drm/controlD64/device/config",
      "/sys/class/drm/renderD128/device/config",
      "/usr/share/libdrm/amdgpu.ids"};
  for (const char* item : kReadWriteList)
    permissions->push_back(BrokerFilePermission::ReadWrite(item));

  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 + "/"));
  }
}

void AddNvidiaGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  static const char* const kReadOnlyList[] = {
      // To support threads in mesa we use --gpu-sandbox-start-early and
      // that requires the following libs and files to be accessible.
      "/etc/ld.so.cache",
      "/usr/lib64/libgallium_dri.so",
      "/usr/lib64/dri/nouveau_dri.so",
      "/usr/lib64/dri/radeonsi_dri.so",
      "/usr/lib64/dri/swrast_dri.so",
      "/usr/lib64/libEGL.so.1",
      "/usr/lib64/libEGL_mesa.so.0",
      "/usr/lib64/libGLESv2.so.2",
      "/usr/lib64/libGLdispatch.so.0",
      "/usr/lib64/libdrm_amdgpu.so.1",
      "/usr/lib64/libdrm_nouveau.so.2",
      "/usr/lib64/libdrm_radeon.so.1",
      "/usr/lib64/libelf.so.1",
      "/usr/lib64/libglapi.so.0",
      "/usr/share/glvnd/egl_vendor.d",
      "/usr/share/glvnd/egl_vendor.d/50_mesa.json"};
  for (const char* item : kReadOnlyList) {
    permissions->push_back(BrokerFilePermission::ReadOnly(item));
  }

  AddDrmGpuPermissions(permissions);
}

void AddIntelGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  static const char* const kReadOnlyList[] = {
      // To support threads in mesa we use --gpu-sandbox-start-early and
      // that requires the following libs and files to be accessible.
      "/usr/lib64/libgallium_dri.so",
      "/usr/lib64/libEGL.so.1", "/usr/lib64/libGLESv2.so.2",
      "/usr/lib64/libelf.so.1", "/usr/lib64/libglapi.so.0",
      "/usr/lib64/libdrm_amdgpu.so.1", "/usr/lib64/libdrm_radeon.so.1",
      "/usr/lib64/libdrm_nouveau.so.2", "/usr/lib64/dri/crocus_dri.so",
      "/usr/lib64/dri/i965_dri.so", "/usr/lib64/dri/iris_dri.so",
      "/usr/lib64/dri/swrast_dri.so", "/usr/lib64/libzstd.so.1",
      // Allow libglvnd files and libs.
      "/usr/share/glvnd/egl_vendor.d",
      "/usr/share/glvnd/egl_vendor.d/50_mesa.json",
      "/usr/lib64/libEGL_mesa.so.0", "/usr/lib64/libGLdispatch.so.0",
      // Case of when the only libc++abi.so.1 is preloaded.
      // See: crbug.com/1366646
      "/usr/lib64/libc++.so.1"};
  for (const char* item : kReadOnlyList)
    permissions->push_back(BrokerFilePermission::ReadOnly(item));

  AddDrmGpuPermissions(permissions);
}

void AddVirtIOGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  static const char* const kReadOnlyList[] = {
      "/etc/ld.so.cache",
      // To support threads in mesa we use --gpu-sandbox-start-early and
      // that requires the following libs and files to be accessible.
      // "/sys", "/sys/dev", "/sys/dev/char", "/sys/devices" are probed in order
      // to use kms_swrast.
      "/sys",
      "/sys/dev",
      "/usr/lib64/libdrm_amdgpu.so.1",
      "/usr/lib64/libdrm_radeon.so.1",
      "/usr/lib64/libdrm_nouveau.so.2",
      "/usr/lib64/libelf.so.1",
      "/usr/lib64/libEGL.so.1",
      "/usr/lib64/libGLESv2.so.2",
      "/usr/lib64/libEGL_mesa.so.0",
      "/usr/lib64/libGLdispatch.so.0",
      "/usr/lib64/libglapi.so.0",
      "/usr/lib64/libc++.so.1",
      "/usr/lib64/libgallium_dri.so",
      // If kms_swrast_dri is not usable, swrast_dri is used instead.
      "/usr/lib64/dri/swrast_dri.so",
      "/usr/lib64/dri/kms_swrast_dri.so",
      "/usr/lib64/dri/virtio_gpu_dri.so",
      "/usr/share/glvnd/egl_vendor.d",
      "/usr/share/glvnd/egl_vendor.d/50_mesa.json",
  };

  for (const char* item : kReadOnlyList) {
    permissions->push_back(BrokerFilePermission::ReadOnly(item));
  }

  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::ReadOnly(path));
    permissions->push_back(BrokerFilePermission::ReadOnlyRecursive(path + "/"));
  }

  AddDrmGpuPermissions(permissions);
}

void AddArmGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  static const char kLdSoCache[] = "/etc/ld.so.cache";

  // Files needed by the ARM GPU userspace.
  permissions->push_back(BrokerFilePermission::ReadOnly(kLdSoCache));
  permissions->push_back(BrokerFilePermission::ReadOnly(kLibGlesPath));
  permissions->push_back(BrokerFilePermission::ReadOnly(kLibEglPath));

  AddArmMaliGpuPermissions(permissions);
}

// Need to look in vendor paths for custom vendor implementations.
static const char* const kAllowedChromecastPaths[] = {
    "/oem_cast_shlib/", "/system/vendor/lib/", "/system/lib/",
    "/system/chrome/lib/"};

void AddChromecastArmGpuPermissions(
    std::vector<BrokerFilePermission>* permissions) {
  // Device file needed by the ARM GPU userspace.
  static const char kMali0Path[] = "/dev/mali0";
  permissions->push_back(BrokerFilePermission::ReadWrite(kMali0Path));

  // Files needed by the ARM GPU userspace.
  static const char* const kReadOnlyLibraries[] = {"libGLESv2.so.2",
                                                   "libEGL.so.1",
                                                   // Allow ANGLE libraries.
                                                   "libGLESv2.so", "libEGL.so"};

  for (const char* library : kReadOnlyLibraries) {
    for (const char* path : kAllowedChromecastPaths) {
      const std::string library_path(std::string(path) + std::string(library));
      permissions->push_back(BrokerFilePermission::ReadOnly(library_path));
    }
  }

  static const char kLdSoCache[] = "/etc/ld.so.cache";
  permissions->push_back(BrokerFilePermission::ReadOnly(kLdSoCache));

  base::FileEnumerator enumerator(
      base::FilePath(FILE_PATH_LITERAL("/dev/dri/")), false /* recursive */,
      base::FileEnumerator::FILES, FILE_PATH_LITERAL("renderD*"));
  for (base::FilePath name = enumerator.Next(); !name.empty();
       name = enumerator.Next()) {
    permissions->push_back(BrokerFilePermission::ReadWrite(name.value()));
  }
}

void AddVulkanICDPermissions(std::vector<BrokerFilePermission>* permissions) {
  static const char* const kReadOnlyICDPrefixes[] = {"/usr/share/vulkan/icd.d",
                                                     "/etc/vulkan/icd.d"};

  static const char* const kReadOnlyICDList[] = {
      "intel_icd.x86_64.json", "nvidia_icd.json", "radeon_icd.x86_64.json",
      "mali_icd.json", "freedreno_icd.aarch64.json"};

  for (std::string prefix : kReadOnlyICDPrefixes) {
    permissions->push_back(BrokerFilePermission::ReadOnly(prefix));
    for (const char* json : kReadOnlyICDList) {
      permissions->push_back(
          BrokerFilePermission::ReadOnly(prefix + "/" + json));
    }
  }
}

void AddStandardGpuPermissions(std::vector<BrokerFilePermission>* permissions) {
  static const char kDriCardBasePath[] = "/dev/dri/card";
  static const char kNvidiaCtlPath[] = "/dev/nvidiactl";
  static const char kNvidiaDeviceBasePath[] = "/dev/nvidia";
  static const char kNvidiaDeviceModeSetPath[] = "/dev/nvidia-modeset";
  static const char kNvidiaParamsPath[] = "/proc/driver/nvidia/params";
  static const char kDevShm[] = "/dev/shm/";
  // For shared memory.
  permissions->push_back(
      BrokerFilePermission::ReadWriteCreateTemporaryRecursive(kDevShm));

  // For DRI cards.
  for (int i = 0; i <= 9; ++i) {
    permissions->push_back(BrokerFilePermission::ReadWrite(
        base::StringPrintf("%s%d", kDriCardBasePath, i)));
  }

  // For Nvidia GLX driver.
  permissions->push_back(BrokerFilePermission::ReadWrite(kNvidiaCtlPath));
  for (int i = 0; i < 10; ++i) {
    permissions->push_back(BrokerFilePermission::ReadWrite(
        base::StringPrintf("%s%d", kNvidiaDeviceBasePath, i)));
  }
  permissions->push_back(
      BrokerFilePermission::ReadWrite(kNvidiaDeviceModeSetPath));
  permissions->push_back(BrokerFilePermission::ReadOnly(kNvidiaParamsPath));

  // For SwiftShader
  base::FilePath module_path;
  if (base::PathService::Get(base::DIR_MODULE, &module_path)) {
    std::string sw_path =
        module_path.Append("libvk_swiftshader.so").MaybeAsASCII();
    if (!sw_path.empty()) {
      permissions->push_back(BrokerFilePermission::ReadOnly(sw_path));
    }
  }
}

void LoadArmGpuLibraries() {
#if BUILDFLAG(IS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
  // This environmental variable needs to be set before we load libMali if we
  // want to instantiate protected Vulkan device queues.
  static const char kMaliConfVar[] = "MALI_PLATFORM_CONFIG";
  // Note this function will only fail if we run out of memory entirely, in
  // which case we would have much bigger problems, so we don't bother to check
  // the return value.
  setenv(kMaliConfVar, kMaliConfPath, 1);
#endif

  // Preload the Mali library.
  if (UseChromecastSandboxAllowlist()) {
    for (const char* path : kAllowedChromecastPaths) {
      const std::string library_path(std::string(path) +
                                     std::string("libMali.so"));
      if (dlopen(library_path.c_str(), dlopen_flag))
        break;
    }
  } else {
    bool is_mali = dlopen(kLibMaliPath, dlopen_flag) != nullptr;

    // Preload the Tegra V4L2 (video decode acceleration) library.
    bool is_tegra = dlopen(kLibTegraPath, dlopen_flag) != nullptr;

    // Preload mesa related libraries for devices which use mesa
    // (ie. not mali or tegra):
    if (!is_mali && !is_tegra &&
        (nullptr != dlopen("libglapi.so.0", dlopen_flag))) {
      auto driver_paths = std::to_array<const char*>({
          "/usr/lib64/libgallium_dri.so",
#if defined(DRI_DRIVER_DIR)
          DRI_DRIVER_DIR "/msm_dri.so",
          DRI_DRIVER_DIR "/panfrost_dri.so",
          DRI_DRIVER_DIR "/mediatek_dri.so",
          DRI_DRIVER_DIR "/rockchip_dri.so",
          DRI_DRIVER_DIR "/asahi_dri.so",
#else
          "/usr/lib64/dri/msm_dri.so",
          "/usr/lib64/dri/panfrost_dri.so",
          "/usr/lib64/dri/mediatek_dri.so",
          "/usr/lib64/dri/rockchip_dri.so",
          "/usr/lib64/dri/asahi_dri.so",
          "/usr/lib/dri/msm_dri.so",
          "/usr/lib/dri/panfrost_dri.so",
          "/usr/lib/dri/mediatek_dri.so",
          "/usr/lib/dri/rockchip_dri.so",
          "/usr/lib/dri/asahi_dri.so",
#endif
          nullptr,
      });

      for (int i = 0; driver_paths[i] != nullptr; i++)
        dlopen(driver_paths[i], dlopen_flag);
    }
  }
}

bool LoadAmdGpuLibraries() {
  // Preload the amdgpu-dependent libraries.
  if (nullptr == dlopen("libglapi.so", dlopen_flag)) {
    LOG(ERROR) << "dlopen(libglapi.so) failed with error: " << dlerror();
    return false;
  }

  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, dlopen_flag)) {
    LOG(ERROR) << "dlopen(radeonsi_dri.so) failed with error: " << dlerror();
    return false;
  }
  return true;
}

bool LoadNvidiaLibraries() {
  // The driver may lazily load several XCB libraries. It's not an error on
  // wayland-only systems for them to be missing.
  const char* kLibraries[] = {
      "libxcb-dri3.so.0",
      "libxcb-glx.so.0",
      "libxcb-present.so.0",
      "libxcb-sync.so.1",
  };
  for (const auto* library : kLibraries) {
    if (!dlopen(library, dlopen_flag))
      LOG(WARNING) << "dlopen(" << library
                   << ") failed with error: " << dlerror();
  }
  return true;
}

void LoadVulkanLibraries() {
  // Try to preload Vulkan libraries. Failure is not an error as not all may be
  // present.
  dlopen("libvulkan.so.1", dlopen_flag);
  dlopen("libvulkan_radeon.so", dlopen_flag);
  dlopen("libvulkan_intel.so", dlopen_flag);
  dlopen("libGLX_nvidia.so.0", dlopen_flag);
  dlopen("libvulkan_freedreno.so", dlopen_flag);
}

void LoadChromecastV4L2Libraries() {
  for (const char* path : kAllowedChromecastPaths) {
    const std::string library_path(std::string(path) +
                                   std::string("libvpcodec.so"));
    if (dlopen(library_path.c_str(), dlopen_flag))
      break;
  }
}

}  // namespace

sandbox::syscall_broker::BrokerCommandSet CommandSetForGPU(
    const sandbox::policy::SandboxLinux::Options& options) {
  sandbox::syscall_broker::BrokerCommandSet command_set;
  command_set.set(sandbox::syscall_broker::COMMAND_ACCESS);
  command_set.set(sandbox::syscall_broker::COMMAND_OPEN);
  command_set.set(sandbox::syscall_broker::COMMAND_STAT);
  if (IsChromeOS() &&
      (options.use_amd_specific_policies ||
       options.use_intel_specific_policies ||
       options.use_nvidia_specific_policies ||
       options.use_virtio_specific_policies || IsArchitectureArm())) {
    command_set.set(sandbox::syscall_broker::COMMAND_READLINK);
  }
  return command_set;
}

std::vector<BrokerFilePermission> FilePermissionsForGpu(
    const sandbox::policy::SandboxSeccompBPF::Options& options) {
  // All GPU process policies need this file brokered out.
  static const char kDriRcPath[] = "/etc/drirc";
  std::vector<BrokerFilePermission> permissions = {
      BrokerFilePermission::ReadOnly(kDriRcPath)};

  AddVulkanICDPermissions(&permissions);

  if (IsChromeOS()) {
    // Permissions are additive, there can be multiple GPUs in the system.
    AddStandardChromeOsPermissions(&permissions);
    if (UseV4L2Codec(options)) {
      AddV4L2GpuPermissions(&permissions, options);
    }
    if (IsArchitectureArm()) {
      AddImgPvrGpuPermissions(&permissions);
      AddArmGpuPermissions(&permissions);
      // Add standard DRM permissions for snapdragon:
      AddDrmGpuPermissions(&permissions);
      // Following discrete GPUs can be plugged in via USB4 on ARM systems.
    }
    if (options.use_amd_specific_policies) {
      AddAmdGpuPermissions(&permissions);
    }
    if (options.use_intel_specific_policies) {
      AddIntelGpuPermissions(&permissions);
    }
    if (options.use_nvidia_specific_policies) {
      AddStandardGpuPermissions(&permissions);
      AddNvidiaGpuPermissions(&permissions);
    }
    if (options.use_virtio_specific_policies) {
      AddVirtIOGpuPermissions(&permissions);
    }
    return permissions;
  }

  if (UseChromecastSandboxAllowlist()) {
    if (UseV4L2Codec(options)) {
      AddV4L2GpuPermissions(&permissions, options);
    }

    if (IsArchitectureArm()) {
      AddChromecastArmGpuPermissions(&permissions);
      return permissions;
    }
  }

  AddStandardGpuPermissions(&permissions);
  return permissions;
}

bool LoadLibrariesForGpu(
    const sandbox::policy::SandboxSeccompBPF::Options& options) {
  LoadVulkanLibraries();
  if (IsArchitectureArm()) {
    LoadArmGpuLibraries();
  }
  if (IsChromeOS()) {
    if (options.use_amd_specific_policies) {
      if (!LoadAmdGpuLibraries())
        return false;
    }
  } else {
    if (UseChromecastSandboxAllowlist() && IsArchitectureArm()) {
      if (UseV4L2Codec(options)) {
        LoadChromecastV4L2Libraries();
      }
    }
  }
  if (options.use_nvidia_specific_policies)
    return LoadNvidiaLibraries();
  return true;
}

bool GpuPreSandboxHook(sandbox::policy::SandboxLinux::Options options) {
  sandbox::policy::SandboxLinux::GetInstance()->StartBrokerProcess(
      CommandSetForGPU(options), FilePermissionsForGpu(options), options);

  if (!LoadLibrariesForGpu(options))
    return false;

  // TODO(tsepez): enable namspace sandbox here once crashes are understood.

  errno = 0;
  return true;
}

}  // namespace content
