• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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 
5 #include "content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h"
6 
7 #include <dlfcn.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <sys/socket.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 
15 #include <string>
16 #include <vector>
17 
18 #include "base/bind.h"
19 #include "base/compiler_specific.h"
20 #include "base/logging.h"
21 #include "base/memory/scoped_ptr.h"
22 #include "build/build_config.h"
23 #include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
24 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
25 #include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
26 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
27 #include "sandbox/linux/services/linux_syscalls.h"
28 
29 using sandbox::ErrorCode;
30 using sandbox::SandboxBPF;
31 using sandbox::SyscallSets;
32 
33 namespace content {
34 
35 namespace {
36 
IsChromeOS()37 inline bool IsChromeOS() {
38 #if defined(OS_CHROMEOS)
39   return true;
40 #else
41   return false;
42 #endif
43 }
44 
IsArchitectureArm()45 inline bool IsArchitectureArm() {
46 #if defined(__arm__)
47   return true;
48 #else
49   return false;
50 #endif
51 }
52 
AddArmMaliGpuWhitelist(std::vector<std::string> * read_whitelist,std::vector<std::string> * write_whitelist)53 void AddArmMaliGpuWhitelist(std::vector<std::string>* read_whitelist,
54                             std::vector<std::string>* write_whitelist) {
55   // Device file needed by the ARM GPU userspace.
56   static const char kMali0Path[] = "/dev/mali0";
57 
58   // Devices needed for video decode acceleration on ARM.
59   static const char kDevMfcDecPath[] = "/dev/mfc-dec";
60   static const char kDevGsc1Path[] = "/dev/gsc1";
61 
62   // Devices needed for video encode acceleration on ARM.
63   static const char kDevMfcEncPath[] = "/dev/mfc-enc";
64 
65   read_whitelist->push_back(kMali0Path);
66   read_whitelist->push_back(kDevMfcDecPath);
67   read_whitelist->push_back(kDevGsc1Path);
68   read_whitelist->push_back(kDevMfcEncPath);
69 
70   write_whitelist->push_back(kMali0Path);
71   write_whitelist->push_back(kDevMfcDecPath);
72   write_whitelist->push_back(kDevGsc1Path);
73   write_whitelist->push_back(kDevMfcEncPath);
74 }
75 
AddArmGpuWhitelist(std::vector<std::string> * read_whitelist,std::vector<std::string> * write_whitelist)76 void AddArmGpuWhitelist(std::vector<std::string>* read_whitelist,
77                         std::vector<std::string>* write_whitelist) {
78   // On ARM we're enabling the sandbox before the X connection is made,
79   // so we need to allow access to |.Xauthority|.
80   static const char kXAuthorityPath[] = "/home/chronos/.Xauthority";
81   static const char kLdSoCache[] = "/etc/ld.so.cache";
82 
83   // Files needed by the ARM GPU userspace.
84   static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
85   static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
86 
87   read_whitelist->push_back(kXAuthorityPath);
88   read_whitelist->push_back(kLdSoCache);
89   read_whitelist->push_back(kLibGlesPath);
90   read_whitelist->push_back(kLibEglPath);
91 
92   AddArmMaliGpuWhitelist(read_whitelist, write_whitelist);
93 }
94 
95 class CrosArmGpuBrokerProcessPolicy : public CrosArmGpuProcessPolicy {
96  public:
Create()97   static sandbox::SandboxBPFPolicy* Create() {
98     return new CrosArmGpuBrokerProcessPolicy();
99   }
~CrosArmGpuBrokerProcessPolicy()100   virtual ~CrosArmGpuBrokerProcessPolicy() {}
101 
102   virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
103                                     int system_call_number) const OVERRIDE;
104 
105  private:
CrosArmGpuBrokerProcessPolicy()106   CrosArmGpuBrokerProcessPolicy() : CrosArmGpuProcessPolicy(false) {}
107   DISALLOW_COPY_AND_ASSIGN(CrosArmGpuBrokerProcessPolicy);
108 };
109 
110 // A GPU broker policy is the same as a GPU policy with open and
111 // openat allowed.
EvaluateSyscall(SandboxBPF * sandbox,int sysno) const112 ErrorCode CrosArmGpuBrokerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
113     int sysno) const {
114   switch (sysno) {
115     case __NR_access:
116     case __NR_open:
117     case __NR_openat:
118       return ErrorCode(ErrorCode::ERR_ALLOWED);
119     default:
120       return CrosArmGpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
121   }
122 }
123 
124 }  // namespace
125 
CrosArmGpuProcessPolicy(bool allow_shmat)126 CrosArmGpuProcessPolicy::CrosArmGpuProcessPolicy(bool allow_shmat)
127     : allow_shmat_(allow_shmat) {}
128 
~CrosArmGpuProcessPolicy()129 CrosArmGpuProcessPolicy::~CrosArmGpuProcessPolicy() {}
130 
EvaluateSyscall(SandboxBPF * sandbox,int sysno) const131 ErrorCode CrosArmGpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
132                                                    int sysno) const {
133 #if defined(__arm__)
134   if (allow_shmat_ && sysno == __NR_shmat)
135     return ErrorCode(ErrorCode::ERR_ALLOWED);
136 #endif  // defined(__arm__)
137 
138   switch (sysno) {
139 #if defined(__arm__)
140     // ARM GPU sandbox is started earlier so we need to allow networking
141     // in the sandbox.
142     case __NR_connect:
143     case __NR_getpeername:
144     case __NR_getsockname:
145     case __NR_sysinfo:
146     case __NR_uname:
147       return ErrorCode(ErrorCode::ERR_ALLOWED);
148     // Allow only AF_UNIX for |domain|.
149     case __NR_socket:
150     case __NR_socketpair:
151       return sandbox->Cond(0, ErrorCode::TP_32BIT,
152                            ErrorCode::OP_EQUAL, AF_UNIX,
153                            ErrorCode(ErrorCode::ERR_ALLOWED),
154                            ErrorCode(EPERM));
155 #endif  // defined(__arm__)
156     default:
157       if (SyscallSets::IsAdvancedScheduler(sysno))
158         return ErrorCode(ErrorCode::ERR_ALLOWED);
159 
160       // Default to the generic GPU policy.
161       return GpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
162   }
163 }
164 
PreSandboxHook()165 bool CrosArmGpuProcessPolicy::PreSandboxHook() {
166   DCHECK(IsChromeOS() && IsArchitectureArm());
167   // Create a new broker process.
168   DCHECK(!broker_process());
169 
170   std::vector<std::string> read_whitelist_extra;
171   std::vector<std::string> write_whitelist_extra;
172   // Add ARM-specific files to whitelist in the broker.
173 
174   AddArmGpuWhitelist(&read_whitelist_extra, &write_whitelist_extra);
175   InitGpuBrokerProcess(CrosArmGpuBrokerProcessPolicy::Create,
176                        read_whitelist_extra,
177                        write_whitelist_extra);
178 
179   const int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE;
180 
181   // Preload the Mali library.
182   dlopen("/usr/lib/libmali.so", dlopen_flag);
183   // Preload the Tegra V4L2 (video decode acceleration) library.
184   dlopen("/usr/lib/libtegrav4l2.so", dlopen_flag);
185   // Resetting errno since platform-specific libraries will fail on other
186   // platforms.
187   errno = 0;
188 
189   return true;
190 }
191 
192 }  // namespace content
193