hardware_video_decoding_sandbox_hook_linux.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/gpu/sandbox/hardware_video_decoding_sandbox_hook_linux.h"
  5. #include <dlfcn.h>
  6. #include <sys/stat.h>
  7. #include "base/strings/stringprintf.h"
  8. #include "media/gpu/buildflags.h"
  9. #if BUILDFLAG(USE_VAAPI)
  10. #include "media/gpu/vaapi/vaapi_wrapper.h"
  11. #endif
  12. using sandbox::syscall_broker::BrokerFilePermission;
  13. namespace media {
  14. bool HardwareVideoDecodingPreSandboxHook(
  15. sandbox::policy::SandboxLinux::Options options) {
  16. sandbox::syscall_broker::BrokerCommandSet command_set;
  17. std::vector<BrokerFilePermission> permissions;
  18. #if BUILDFLAG(USE_V4L2_CODEC)
  19. command_set.set(sandbox::syscall_broker::COMMAND_OPEN);
  20. // Device nodes for V4L2 video decode accelerator drivers.
  21. // We do not use a FileEnumerator because the device files may not exist
  22. // yet when the sandbox is created. But since we are restricting access
  23. // to the video-dec* and media-dec* prefixes we know that we cannot
  24. // authorize a non-decoder device by accident.
  25. static constexpr size_t MAX_V4L2_DECODERS = 5;
  26. static const base::FilePath::CharType kDevicePath[] =
  27. FILE_PATH_LITERAL("/dev/");
  28. static const base::FilePath::CharType kVideoDecBase[] = "video-dec";
  29. static const base::FilePath::CharType kMediaDecBase[] = "media-dec";
  30. for (size_t i = 0; i < MAX_V4L2_DECODERS; i++) {
  31. std::ostringstream decoderPath;
  32. decoderPath << kDevicePath << kVideoDecBase << i;
  33. permissions.push_back(BrokerFilePermission::ReadWrite(decoderPath.str()));
  34. std::ostringstream mediaDevicePath;
  35. mediaDevicePath << kDevicePath << kMediaDecBase << i;
  36. permissions.push_back(
  37. BrokerFilePermission::ReadWrite(mediaDevicePath.str()));
  38. }
  39. // Image processor used on ARM platforms.
  40. // TODO(b/195769334): not all V4L2 platforms need an image processor for video
  41. // decoding. Look into whether we can restrict this permission to only
  42. // platforms that need it.
  43. static const char kDevImageProc0Path[] = "/dev/image-proc0";
  44. permissions.push_back(BrokerFilePermission::ReadWrite(kDevImageProc0Path));
  45. #elif BUILDFLAG(USE_VAAPI)
  46. command_set.set(sandbox::syscall_broker::COMMAND_OPEN);
  47. if (options.use_amd_specific_policies) {
  48. command_set.set(sandbox::syscall_broker::COMMAND_ACCESS);
  49. command_set.set(sandbox::syscall_broker::COMMAND_STAT);
  50. command_set.set(sandbox::syscall_broker::COMMAND_READLINK);
  51. permissions.push_back(BrokerFilePermission::ReadOnly("/dev/dri"));
  52. static const char* kDevices[] = {"/sys/dev/char", "/sys/devices"};
  53. for (const char* item : kDevices) {
  54. std::string path(item);
  55. permissions.push_back(
  56. BrokerFilePermission::StatOnlyWithIntermediateDirs(path));
  57. permissions.push_back(
  58. BrokerFilePermission::ReadOnlyRecursive(path + "/"));
  59. }
  60. }
  61. // TODO(b/195769334): for now, this is only needed for two use cases: the
  62. // legacy VaapiVideoDecodeAccelerator and AMD. However, we'll likely need this
  63. // unconditionally so that we can allocate dma-bufs.
  64. for (int i = 128; i <= 137; ++i) {
  65. const std::string path = base::StringPrintf("/dev/dri/renderD%d", i);
  66. struct stat st;
  67. if (stat(path.c_str(), &st) == 0) {
  68. permissions.push_back(options.use_amd_specific_policies
  69. ? BrokerFilePermission::ReadWrite(path)
  70. : BrokerFilePermission::ReadOnly(path));
  71. }
  72. }
  73. #endif // BUILDFLAG(USE_V4L2_CODEC)
  74. sandbox::policy::SandboxLinux::GetInstance()->StartBrokerProcess(
  75. command_set, permissions, sandbox::policy::SandboxLinux::PreSandboxHook(),
  76. options);
  77. // TODO(b/195769334): the hardware video decoding sandbox is really only
  78. // useful when building with VA-API or V4L2 (otherwise, we're not really doing
  79. // hardware video decoding). Consider restricting the kHardwareVideoDecoding
  80. // sandbox type to exist only in those configurations so that the presandbox
  81. // hook is only reached in those scenarios. As it is now,
  82. // kHardwareVideoDecoding exists for all ash-chrome builds because
  83. // chrome/browser/ash/arc/video/gpu_arc_video_service_host.cc depends on it
  84. // and that file is built for ash-chrome regardless of VA-API/V4L2. That means
  85. // that bots like linux-chromeos-rel end up reaching this presandbox hook.
  86. #if BUILDFLAG(USE_VAAPI)
  87. VaapiWrapper::PreSandboxInitialization();
  88. if (options.use_amd_specific_policies) {
  89. const char* radeonsi_lib = "/usr/lib64/dri/radeonsi_dri.so";
  90. #if defined(DRI_DRIVER_DIR)
  91. radeonsi_lib = DRI_DRIVER_DIR "/radeonsi_dri.so";
  92. #endif
  93. if (nullptr ==
  94. dlopen(radeonsi_lib, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) {
  95. LOG(ERROR) << "dlopen(radeonsi_dri.so) failed with error: " << dlerror();
  96. return false;
  97. }
  98. }
  99. #elif BUILDFLAG(USE_V4L2_CODEC) && BUILDFLAG(USE_LIBV4L2)
  100. #if defined(__aarch64__)
  101. dlopen("/usr/lib64/libv4l2.so", RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
  102. #else
  103. dlopen("/usr/lib/libv4l2.so", RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
  104. #endif // defined(__aarch64__)
  105. #endif // BUILDFLAG(USE_VAAPI)
  106. return true;
  107. }
  108. } // namespace media