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/compiler_specific.h" 19#include "base/logging.h" 20#include "base/memory/scoped_ptr.h" 21#include "build/build_config.h" 22#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h" 23#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" 24#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h" 25#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 26#include "sandbox/linux/services/linux_syscalls.h" 27 28using sandbox::ErrorCode; 29using sandbox::SandboxBPF; 30using sandbox::SyscallSets; 31 32namespace content { 33 34namespace { 35 36inline bool IsChromeOS() { 37#if defined(OS_CHROMEOS) 38 return true; 39#else 40 return false; 41#endif 42} 43 44inline bool IsArchitectureArm() { 45#if defined(__arm__) 46 return true; 47#else 48 return false; 49#endif 50} 51 52void AddArmMaliGpuWhitelist(std::vector<std::string>* read_whitelist, 53 std::vector<std::string>* write_whitelist) { 54 // Device file needed by the ARM GPU userspace. 55 static const char kMali0Path[] = "/dev/mali0"; 56 57 // Devices needed for video decode acceleration on ARM. 58 static const char kDevMfcDecPath[] = "/dev/mfc-dec"; 59 static const char kDevGsc1Path[] = "/dev/gsc1"; 60 61 // Devices needed for video encode acceleration on ARM. 62 static const char kDevMfcEncPath[] = "/dev/mfc-enc"; 63 64 read_whitelist->push_back(kMali0Path); 65 read_whitelist->push_back(kDevMfcDecPath); 66 read_whitelist->push_back(kDevGsc1Path); 67 read_whitelist->push_back(kDevMfcEncPath); 68 69 write_whitelist->push_back(kMali0Path); 70 write_whitelist->push_back(kDevMfcDecPath); 71 write_whitelist->push_back(kDevGsc1Path); 72 write_whitelist->push_back(kDevMfcEncPath); 73} 74 75void AddArmTegraGpuWhitelist(std::vector<std::string>* read_whitelist, 76 std::vector<std::string>* write_whitelist) { 77 // Device files needed by the Tegra GPU userspace. 78 static const char kDevNvhostCtrlPath[] = "/dev/nvhost-ctrl"; 79 static const char kDevNvhostGr2dPath[] = "/dev/nvhost-gr2d"; 80 static const char kDevNvhostGr3dPath[] = "/dev/nvhost-gr3d"; 81 static const char kDevNvhostIspPath[] = "/dev/nvhost-isp"; 82 static const char kDevNvhostViPath[] = "/dev/nvhost-vi"; 83 static const char kDevNvmapPath[] = "/dev/nvmap"; 84 static const char kDevTegraSemaPath[] = "/dev/tegra_sema"; 85 86 read_whitelist->push_back(kDevNvhostCtrlPath); 87 read_whitelist->push_back(kDevNvhostGr2dPath); 88 read_whitelist->push_back(kDevNvhostGr3dPath); 89 read_whitelist->push_back(kDevNvhostIspPath); 90 read_whitelist->push_back(kDevNvhostViPath); 91 read_whitelist->push_back(kDevNvmapPath); 92 read_whitelist->push_back(kDevTegraSemaPath); 93 94 write_whitelist->push_back(kDevNvhostCtrlPath); 95 write_whitelist->push_back(kDevNvhostGr2dPath); 96 write_whitelist->push_back(kDevNvhostGr3dPath); 97 write_whitelist->push_back(kDevNvhostIspPath); 98 write_whitelist->push_back(kDevNvhostViPath); 99 write_whitelist->push_back(kDevNvmapPath); 100 write_whitelist->push_back(kDevTegraSemaPath); 101} 102 103void AddArmGpuWhitelist(std::vector<std::string>* read_whitelist, 104 std::vector<std::string>* write_whitelist) { 105 // On ARM we're enabling the sandbox before the X connection is made, 106 // so we need to allow access to |.Xauthority|. 107 static const char kXAuthorityPath[] = "/home/chronos/.Xauthority"; 108 static const char kLdSoCache[] = "/etc/ld.so.cache"; 109 110 // Files needed by the ARM GPU userspace. 111 static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2"; 112 static const char kLibEglPath[] = "/usr/lib/libEGL.so.1"; 113 114 read_whitelist->push_back(kXAuthorityPath); 115 read_whitelist->push_back(kLdSoCache); 116 read_whitelist->push_back(kLibGlesPath); 117 read_whitelist->push_back(kLibEglPath); 118 119 AddArmMaliGpuWhitelist(read_whitelist, write_whitelist); 120 AddArmTegraGpuWhitelist(read_whitelist, write_whitelist); 121} 122 123class CrosArmGpuBrokerProcessPolicy : public CrosArmGpuProcessPolicy { 124 public: 125 CrosArmGpuBrokerProcessPolicy() : CrosArmGpuProcessPolicy(false) {} 126 virtual ~CrosArmGpuBrokerProcessPolicy() {} 127 128 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, 129 int system_call_number) const OVERRIDE; 130 131 private: 132 DISALLOW_COPY_AND_ASSIGN(CrosArmGpuBrokerProcessPolicy); 133}; 134 135// A GPU broker policy is the same as a GPU policy with open and 136// openat allowed. 137ErrorCode CrosArmGpuBrokerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox, 138 int sysno) const { 139 switch (sysno) { 140 case __NR_access: 141 case __NR_open: 142 case __NR_openat: 143 return ErrorCode(ErrorCode::ERR_ALLOWED); 144 default: 145 return CrosArmGpuProcessPolicy::EvaluateSyscall(sandbox, sysno); 146 } 147} 148 149bool EnableArmGpuBrokerPolicyCallback() { 150 return SandboxSeccompBPF::StartSandboxWithExternalPolicy( 151 scoped_ptr<sandbox::SandboxBPFPolicy>(new CrosArmGpuBrokerProcessPolicy)); 152} 153 154} // namespace 155 156CrosArmGpuProcessPolicy::CrosArmGpuProcessPolicy(bool allow_shmat) 157 : allow_shmat_(allow_shmat) {} 158 159CrosArmGpuProcessPolicy::~CrosArmGpuProcessPolicy() {} 160 161ErrorCode CrosArmGpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox, 162 int sysno) const { 163#if defined(__arm__) 164 if (allow_shmat_ && sysno == __NR_shmat) 165 return ErrorCode(ErrorCode::ERR_ALLOWED); 166#endif // defined(__arm__) 167 168 switch (sysno) { 169#if defined(__arm__) 170 // ARM GPU sandbox is started earlier so we need to allow networking 171 // in the sandbox. 172 case __NR_connect: 173 case __NR_getpeername: 174 case __NR_getsockname: 175 case __NR_sysinfo: 176 case __NR_uname: 177 return ErrorCode(ErrorCode::ERR_ALLOWED); 178 // Allow only AF_UNIX for |domain|. 179 case __NR_socket: 180 case __NR_socketpair: 181 return sandbox->Cond(0, ErrorCode::TP_32BIT, 182 ErrorCode::OP_EQUAL, AF_UNIX, 183 ErrorCode(ErrorCode::ERR_ALLOWED), 184 ErrorCode(EPERM)); 185#endif // defined(__arm__) 186 default: 187 if (SyscallSets::IsAdvancedScheduler(sysno)) 188 return ErrorCode(ErrorCode::ERR_ALLOWED); 189 190 // Default to the generic GPU policy. 191 return GpuProcessPolicy::EvaluateSyscall(sandbox, sysno); 192 } 193} 194 195bool CrosArmGpuProcessPolicy::PreSandboxHook() { 196 DCHECK(IsChromeOS() && IsArchitectureArm()); 197 // Create a new broker process. 198 DCHECK(!broker_process()); 199 200 std::vector<std::string> read_whitelist_extra; 201 std::vector<std::string> write_whitelist_extra; 202 // Add ARM-specific files to whitelist in the broker. 203 204 AddArmGpuWhitelist(&read_whitelist_extra, &write_whitelist_extra); 205 InitGpuBrokerProcess(EnableArmGpuBrokerPolicyCallback, 206 read_whitelist_extra, 207 write_whitelist_extra); 208 209 const int dlopen_flag = RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE; 210 211 // Preload the Mali library. 212 dlopen("/usr/lib/libmali.so", dlopen_flag); 213 214 // Preload the Tegra libraries. 215 dlopen("/usr/lib/libnvrm.so", dlopen_flag); 216 dlopen("/usr/lib/libnvrm_graphics.so", dlopen_flag); 217 dlopen("/usr/lib/libnvos.so", dlopen_flag); 218 dlopen("/usr/lib/libnvddk_2d.so", dlopen_flag); 219 dlopen("/usr/lib/libardrv_dynamic.so", dlopen_flag); 220 dlopen("/usr/lib/libnvwsi.so", dlopen_flag); 221 dlopen("/usr/lib/libnvglsi.so", dlopen_flag); 222 dlopen("/usr/lib/libcgdrv.so", dlopen_flag); 223 224 return true; 225} 226 227} // namespace content 228