File: bpf_hardware_video_decoding_policy_linux.cc

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (149 lines) | stat: -rw-r--r-- 5,614 bytes parent folder | download | duplicates (6)
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