1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
// 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 "sandbox/policy/linux/bpf_hardware_video_decoding_policy_linux.h"
#include <linux/kcmp.h>
#include "base/notreached.h"
#include "media/gpu/buildflags.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/policy/linux/sandbox_linux.h"
using sandbox::bpf_dsl::AllOf;
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::ResultExpr;
namespace sandbox::policy {
// static
HardwareVideoDecodingProcessPolicy::PolicyType
HardwareVideoDecodingProcessPolicy::ComputePolicyType(
bool use_amd_specific_policies) {
// TODO(b/210759684): the policy type computation is currently based on the
// GPU. In reality, we should base this on the video decoding hardware. This
// is good enough on ChromeOS but may be not good enough for a Linux system
// with multiple GPUs.
#if BUILDFLAG(USE_VAAPI)
return use_amd_specific_policies ? PolicyType::kVaapiOnAMD
: PolicyType::kVaapiOnIntel;
#elif BUILDFLAG(USE_V4L2_CODEC)
return PolicyType::kV4L2;
#else
// TODO(b/195769334): the hardware video decoding sandbox is really only
// useful when building with VA-API or V4L2 (otherwise, we're not really doing
// hardware video decoding). Consider restricting the kHardwareVideoDecoding
// sandbox type to exist only in those configurations so that the
// HardwareVideoDecodingProcessPolicy is only compiled in those scenarios. As
// it is now, kHardwareVideoDecoding exists for all ash-chrome builds because
// chromeos/ash/experiences/arc/video/gpu_arc_video_service_host.cc depends on
// it and that file is built for ash-chrome regardless of VA-API/V4L2. That
// means that bots like linux-chromeos-rel end up compiling this policy.
NOTREACHED();
#endif
}
HardwareVideoDecodingProcessPolicy::HardwareVideoDecodingProcessPolicy(
PolicyType policy_type)
: policy_type_(policy_type) {}
ResultExpr HardwareVideoDecodingProcessPolicy::EvaluateSyscall(
int system_call_number) const {
switch (policy_type_) {
case PolicyType::kVaapiOnIntel:
return EvaluateSyscallForVaapiOnIntel(system_call_number);
case PolicyType::kVaapiOnAMD:
return EvaluateSyscallForVaapiOnAMD(system_call_number);
case PolicyType::kV4L2:
return EvaluateSyscallForV4L2(system_call_number);
}
}
ResultExpr HardwareVideoDecodingProcessPolicy::EvaluateSyscallForVaapiOnIntel(
int system_call_number) const {
if (SyscallSets::IsTruncate(system_call_number)) {
// Explicitly disallow ftruncate()/truncate() to eliminate the possibility
// that a video decoder process can change the size of a file (including,
// e.g., a dma-buf).
return CrashSIGSYS();
}
if (system_call_number == __NR_ioctl)
return Allow();
auto* sandbox_linux = SandboxLinux::GetInstance();
if (sandbox_linux->ShouldBrokerHandleSyscall(system_call_number))
return sandbox_linux->HandleViaBroker(system_call_number);
return BPFBasePolicy::EvaluateSyscall(system_call_number);
}
ResultExpr HardwareVideoDecodingProcessPolicy::EvaluateSyscallForVaapiOnAMD(
int system_call_number) const {
if (SyscallSets::IsTruncate(system_call_number)) {
// Explicitly disallow ftruncate()/truncate() to eliminate the possibility
// that a video decoder process can change the size of a file (including,
// e.g., a dma-buf).
return CrashSIGSYS();
}
switch (system_call_number) {
case __NR_getdents64:
case __NR_ioctl:
case __NR_sysinfo:
case __NR_sched_setscheduler:
return Allow();
case __NR_sched_setaffinity:
return RestrictSchedTarget(GetPolicyPid(), system_call_number);
case __NR_kcmp: {
const Arg<pid_t> pid1(0);
const Arg<pid_t> pid2(1);
const Arg<int> type(2);
const pid_t policy_pid = GetPolicyPid();
// Only allowed when comparing file handles for the calling thread.
return If(AllOf(pid1 == policy_pid, pid2 == policy_pid,
type == KCMP_FILE),
Allow())
.Else(Error(EPERM));
}
}
auto* sandbox_linux = SandboxLinux::GetInstance();
if (sandbox_linux->ShouldBrokerHandleSyscall(system_call_number))
return sandbox_linux->HandleViaBroker(system_call_number);
return BPFBasePolicy::EvaluateSyscall(system_call_number);
}
ResultExpr HardwareVideoDecodingProcessPolicy::EvaluateSyscallForV4L2(
int system_call_number) const {
if (SyscallSets::IsTruncate(system_call_number)) {
// Explicitly disallow ftruncate()/truncate() to eliminate the possibility
// that a video decoder process can change the size of a file (including,
// e.g., a dma-buf).
return CrashSIGSYS();
}
if (system_call_number == __NR_ioctl)
return Allow();
if (system_call_number == __NR_sched_setaffinity) {
return RestrictSchedTarget(GetPolicyPid(), system_call_number);
}
auto* sandbox_linux = SandboxLinux::GetInstance();
if (sandbox_linux->ShouldBrokerHandleSyscall(system_call_number))
return sandbox_linux->HandleViaBroker(system_call_number);
return BPFBasePolicy::EvaluateSyscall(system_call_number);
}
} // namespace sandbox::policy
|