OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <asm/unistd.h> | 5 #include <asm/unistd.h> |
6 #include <dlfcn.h> | 6 #include <dlfcn.h> |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <linux/audit.h> | 9 #include <linux/audit.h> |
10 #include <linux/filter.h> | 10 #include <linux/filter.h> |
11 #include <signal.h> | 11 #include <signal.h> |
12 #include <string.h> | 12 #include <string.h> |
13 #include <sys/prctl.h> | 13 #include <sys/prctl.h> |
14 #include <sys/stat.h> | 14 #include <sys/stat.h> |
15 #include <sys/types.h> | 15 #include <sys/types.h> |
16 #include <ucontext.h> | 16 #include <ucontext.h> |
17 #include <unistd.h> | 17 #include <unistd.h> |
18 | 18 |
19 #include <vector> | 19 #include <vector> |
20 | 20 |
21 #include "base/command_line.h" | 21 #include "base/command_line.h" |
22 #include "base/logging.h" | 22 #include "base/logging.h" |
23 #include "content/common/sandbox_linux.h" | 23 #include "content/common/sandbox_linux.h" |
24 #include "content/common/sandbox_seccomp_bpf_linux.h" | 24 #include "content/common/sandbox_seccomp_bpf_linux.h" |
25 #include "content/public/common/content_switches.h" | 25 #include "content/public/common/content_switches.h" |
| 26 #include "sandbox/linux/services/broker_process.h" |
26 | 27 |
27 // These are the only architectures supported for now. | 28 // These are the only architectures supported for now. |
28 #if defined(__i386__) || defined(__x86_64__) || \ | 29 #if defined(__i386__) || defined(__x86_64__) || \ |
29 (defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))) | 30 (defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))) |
30 #define SECCOMP_BPF_SANDBOX | 31 #define SECCOMP_BPF_SANDBOX |
31 #endif | 32 #endif |
32 | 33 |
33 #if defined(SECCOMP_BPF_SANDBOX) | 34 #if defined(SECCOMP_BPF_SANDBOX) |
34 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 35 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
35 #include "sandbox/linux/services/linux_syscalls.h" | 36 #include "sandbox/linux/services/linux_syscalls.h" |
36 | 37 |
37 using playground2::arch_seccomp_data; | 38 using playground2::arch_seccomp_data; |
38 using playground2::ErrorCode; | 39 using playground2::ErrorCode; |
39 using playground2::Sandbox; | 40 using playground2::Sandbox; |
| 41 using sandbox::BrokerProcess; |
40 | 42 |
41 namespace { | 43 namespace { |
42 | 44 |
| 45 void StartSandboxWithPolicy(Sandbox::EvaluateSyscall syscall_policy, |
| 46 BrokerProcess* broker_process); |
| 47 |
43 inline bool IsChromeOS() { | 48 inline bool IsChromeOS() { |
44 #if defined(OS_CHROMEOS) | 49 #if defined(OS_CHROMEOS) |
45 return true; | 50 return true; |
46 #else | 51 #else |
47 return false; | 52 return false; |
48 #endif | 53 #endif |
49 } | 54 } |
50 | 55 |
51 inline bool IsArchitectureI386() { | 56 inline bool IsArchitectureI386() { |
52 #if defined(__i386__) | 57 #if defined(__i386__) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 // but not on Linux: crbug.com/137247. | 98 // but not on Linux: crbug.com/137247. |
94 bool is_enabled = IsChromeOS(); | 99 bool is_enabled = IsChromeOS(); |
95 | 100 |
96 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 101 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
97 is_enabled = is_enabled && | 102 is_enabled = is_enabled && |
98 !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode); | 103 !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode); |
99 | 104 |
100 return is_enabled; | 105 return is_enabled; |
101 } | 106 } |
102 | 107 |
103 static const char kDriRcPath[] = "/etc/drirc"; | 108 intptr_t GpuOpenSIGSYS_Handler(const struct arch_seccomp_data& args, |
104 | 109 void* aux_broker_process) { |
105 // TODO(jorgelo): limited to /etc/drirc for now, extend this to cover | 110 RAW_CHECK(aux_broker_process); |
106 // other sandboxed file access cases. | 111 BrokerProcess* broker_process = |
107 int OpenWithCache(const char* pathname, int flags) { | 112 static_cast<BrokerProcess*>(aux_broker_process); |
108 static int drircfd = -1; | 113 switch(args.nr) { |
109 static bool do_open = true; | 114 case __NR_open: |
110 int res = -1; | 115 return broker_process->Open(reinterpret_cast<const char*>(args.args[0]), |
111 | 116 static_cast<int>(args.args[1])); |
112 if (strcmp(pathname, kDriRcPath) == 0 && flags == O_RDONLY) { | 117 case __NR_openat: |
113 if (do_open) { | 118 // Allow using openat() as open(). |
114 drircfd = open(pathname, flags); | 119 if (static_cast<int>(args.args[0]) == AT_FDCWD) { |
115 do_open = false; | 120 return |
116 res = drircfd; | 121 broker_process->Open(reinterpret_cast<const char*>(args.args[1]), |
117 } else { | 122 static_cast<int>(args.args[2])); |
118 // dup() man page: | 123 } else { |
119 // "After a successful return from one of these system calls, | 124 return -EPERM; |
120 // the old and new file descriptors may be used interchangeably. | |
121 // They refer to the same open file description and thus share | |
122 // file offset and file status flags; for example, if the file offset | |
123 // is modified by using lseek(2) on one of the descriptors, | |
124 // the offset is also changed for the other." | |
125 // Since |drircfd| can be dup()'ed and read many times, we need to | |
126 // lseek() it to the beginning of the file before returning. | |
127 // We assume the caller will not keep more than one fd open at any | |
128 // one time. Intel driver code in Mesa that parses /etc/drirc does | |
129 // open()/read()/close() in the same function. | |
130 if (drircfd < 0) { | |
131 errno = ENOENT; | |
132 return -1; | |
133 } | 125 } |
134 int newfd = dup(drircfd); | 126 default: |
135 if (newfd < 0) { | 127 RAW_CHECK(false); |
136 errno = ENOMEM; | 128 return -ENOSYS; |
137 return -1; | |
138 } | |
139 if (lseek(newfd, 0, SEEK_SET) == static_cast<off_t>(-1)) { | |
140 (void) HANDLE_EINTR(close(newfd)); | |
141 errno = ENOMEM; | |
142 return -1; | |
143 } | |
144 res = newfd; | |
145 } | |
146 } else { | |
147 res = open(pathname, flags); | |
148 } | |
149 | |
150 return res; | |
151 } | |
152 | |
153 // We allow the GPU process to open /etc/drirc because it's needed by Mesa. | |
154 // OpenWithCache() has been called before enabling the sandbox, and has cached | |
155 // a file descriptor for /etc/drirc. | |
156 intptr_t GpuOpenSIGSYS_Handler(const struct arch_seccomp_data& args, | |
157 void* aux) { | |
158 uint64_t arg0 = args.args[0]; | |
159 uint64_t arg1 = args.args[1]; | |
160 const char* pathname = reinterpret_cast<const char*>(arg0); | |
161 int flags = static_cast<int>(arg1); | |
162 | |
163 if (strcmp(pathname, kDriRcPath) == 0) { | |
164 int ret = OpenWithCache(pathname, flags); | |
165 return (ret == -1) ? -errno : ret; | |
166 } else { | |
167 return -ENOENT; | |
168 } | 129 } |
169 } | 130 } |
170 | 131 |
171 // The functions below cover all existing i386, x86_64, and ARM system calls; | 132 // The functions below cover all existing i386, x86_64, and ARM system calls; |
172 // excluding syscalls made obsolete in ARM EABI. | 133 // excluding syscalls made obsolete in ARM EABI. |
173 // The implicitly defined sets form a partition of the sets of | 134 // The implicitly defined sets form a partition of the sets of |
174 // system calls. | 135 // system calls. |
175 | 136 |
176 // TODO(jln) we need to restrict the first parameter! | 137 // TODO(jln) we need to restrict the first parameter! |
177 bool IsKill(int sysno) { | 138 bool IsKill(int sysno) { |
(...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 if (IsBaselinePolicyWatched(sysno)) { | 1188 if (IsBaselinePolicyWatched(sysno)) { |
1228 // Previously unseen syscalls. TODO(jln): some of these should | 1189 // Previously unseen syscalls. TODO(jln): some of these should |
1229 // be denied gracefully right away. | 1190 // be denied gracefully right away. |
1230 return Sandbox::Trap(CrashSIGSYS_Handler, NULL); | 1191 return Sandbox::Trap(CrashSIGSYS_Handler, NULL); |
1231 } | 1192 } |
1232 // In any other case crash the program with our SIGSYS handler | 1193 // In any other case crash the program with our SIGSYS handler |
1233 return Sandbox::Trap(CrashSIGSYS_Handler, NULL); | 1194 return Sandbox::Trap(CrashSIGSYS_Handler, NULL); |
1234 } | 1195 } |
1235 | 1196 |
1236 // x86_64 only for now. Needs to be adapted and tested for i386/ARM. | 1197 // x86_64 only for now. Needs to be adapted and tested for i386/ARM. |
1237 ErrorCode GpuProcessPolicy_x86_64(int sysno, void *) { | 1198 ErrorCode GpuProcessPolicy_x86_64(int sysno, void *broker_process) { |
1238 switch(sysno) { | 1199 switch(sysno) { |
1239 case __NR_ioctl: | 1200 case __NR_ioctl: |
1240 #if defined(ADDRESS_SANITIZER) | 1201 #if defined(ADDRESS_SANITIZER) |
1241 // Allow to call sched_getaffinity under AddressSanitizer. | 1202 // Allow to call sched_getaffinity under AddressSanitizer. |
1242 case __NR_sched_getaffinity: | 1203 case __NR_sched_getaffinity: |
1243 #endif | 1204 #endif |
1244 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1205 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1245 case __NR_open: | 1206 case __NR_open: |
1246 // Accelerated video decode is enabled by default only on Chrome OS. | 1207 case __NR_openat: |
1247 if (IsAcceleratedVideoDecodeEnabled()) { | 1208 return Sandbox::Trap(GpuOpenSIGSYS_Handler, broker_process); |
1248 // Accelerated video decode needs to open /dev/dri/card0, and | |
1249 // dup()'ing an already open file descriptor does not work. | |
1250 // Allow open() even though it severely weakens the sandbox, | |
1251 // to test the sandboxing mechanism in general. | |
1252 // TODO(jorgelo): remove this once we solve the libva issue. | |
1253 return ErrorCode(ErrorCode::ERR_ALLOWED); | |
1254 } else { | |
1255 // Hook open() in the GPU process to allow opening /etc/drirc, | |
1256 // needed by Mesa. | |
1257 // The hook needs dup(), lseek(), and close() to be allowed. | |
1258 return Sandbox::Trap(GpuOpenSIGSYS_Handler, NULL); | |
1259 } | |
1260 default: | 1209 default: |
1261 if (IsEventFd(sysno)) | 1210 if (IsEventFd(sysno)) |
1262 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1211 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1263 | 1212 |
1264 // Default on the baseline policy. | 1213 // Default on the baseline policy. |
1265 return BaselinePolicy(sysno); | 1214 return BaselinePolicy(sysno); |
1266 } | 1215 } |
1267 } | 1216 } |
1268 | 1217 |
| 1218 // x86_64 only for now. Needs to be adapted and tested for i386/ARM. |
| 1219 // A GPU broker policy is the same as a GPU policy with open and |
| 1220 // openat allowed. |
| 1221 ErrorCode GpuBrokerProcessPolicy_x86_64(int sysno, void*) { |
| 1222 switch(sysno) { |
| 1223 case __NR_open: |
| 1224 case __NR_openat: |
| 1225 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 1226 default: |
| 1227 return GpuProcessPolicy_x86_64(sysno, NULL); |
| 1228 } |
| 1229 } |
| 1230 |
1269 ErrorCode RendererOrWorkerProcessPolicy(int sysno, void *) { | 1231 ErrorCode RendererOrWorkerProcessPolicy(int sysno, void *) { |
1270 switch (sysno) { | 1232 switch (sysno) { |
1271 case __NR_ioctl: // TODO(jln) investigate legitimate use in the renderer | 1233 case __NR_ioctl: // TODO(jln) investigate legitimate use in the renderer |
1272 // and see if alternatives can be used. | 1234 // and see if alternatives can be used. |
1273 case __NR_fdatasync: | 1235 case __NR_fdatasync: |
1274 case __NR_fsync: | 1236 case __NR_fsync: |
1275 #if defined(__i386__) || defined(__x86_64__) | 1237 #if defined(__i386__) || defined(__x86_64__) |
1276 case __NR_getrlimit: | 1238 case __NR_getrlimit: |
1277 #endif | 1239 #endif |
1278 case __NR_mremap: // See crbug.com/149834. | 1240 case __NR_mremap: // See crbug.com/149834. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 // 64 bits system calls in compatibility mode. | 1313 // 64 bits system calls in compatibility mode. |
1352 ErrorCode AllowAllPolicy(int sysno, void *) { | 1314 ErrorCode AllowAllPolicy(int sysno, void *) { |
1353 if (!Sandbox::isValidSyscallNumber(sysno)) { | 1315 if (!Sandbox::isValidSyscallNumber(sysno)) { |
1354 // TODO(jln) we should not have to do that in a trivial policy. | 1316 // TODO(jln) we should not have to do that in a trivial policy. |
1355 return ErrorCode(ENOSYS); | 1317 return ErrorCode(ENOSYS); |
1356 } else { | 1318 } else { |
1357 return ErrorCode(ErrorCode::ERR_ALLOWED); | 1319 return ErrorCode(ErrorCode::ERR_ALLOWED); |
1358 } | 1320 } |
1359 } | 1321 } |
1360 | 1322 |
| 1323 bool EnableGpuBrokerPolicyCallBack() { |
| 1324 StartSandboxWithPolicy(GpuBrokerProcessPolicy_x86_64, NULL); |
| 1325 return true; |
| 1326 } |
| 1327 |
| 1328 // Start a broker process to handle open() inside the sandbox. |
| 1329 void InitGpuBrokerProcess_x86_64(BrokerProcess** broker_process) { |
| 1330 static const char kDriRcPath[] = "/etc/drirc"; |
| 1331 static const char kDriCard0Path[] = "/dev/dri/card0"; |
| 1332 |
| 1333 CHECK(broker_process); |
| 1334 CHECK(*broker_process == NULL); |
| 1335 |
| 1336 std::vector<std::string> read_whitelist; |
| 1337 read_whitelist.push_back(kDriCard0Path); |
| 1338 read_whitelist.push_back(kDriRcPath); |
| 1339 std::vector<std::string> write_whitelist; |
| 1340 write_whitelist.push_back(kDriCard0Path); |
| 1341 |
| 1342 *broker_process = new BrokerProcess(read_whitelist, write_whitelist); |
| 1343 // Initialize the broker process and give it a sandbox call back. |
| 1344 CHECK((*broker_process)->Init(EnableGpuBrokerPolicyCallBack)); |
| 1345 } |
| 1346 |
1361 // Warms up/preloads resources needed by the policies. | 1347 // Warms up/preloads resources needed by the policies. |
1362 void WarmupPolicy(Sandbox::EvaluateSyscall policy) { | 1348 // Eventually start a broker process and return it in broker_process. |
| 1349 void WarmupPolicy(Sandbox::EvaluateSyscall policy, |
| 1350 BrokerProcess** broker_process) { |
1363 #if defined(__x86_64__) | 1351 #if defined(__x86_64__) |
1364 if (policy == GpuProcessPolicy_x86_64) { | 1352 if (policy == GpuProcessPolicy_x86_64) { |
1365 OpenWithCache(kDriRcPath, O_RDONLY); | 1353 // Create a new broker process. |
| 1354 InitGpuBrokerProcess_x86_64(broker_process); |
1366 // Accelerated video decode dlopen()'s this shared object | 1355 // Accelerated video decode dlopen()'s this shared object |
1367 // inside the sandbox, so preload it now. | 1356 // inside the sandbox, so preload it now. |
1368 // TODO(jorgelo): generalize this to other platforms. | 1357 // TODO(jorgelo): generalize this to other platforms. |
1369 if (IsAcceleratedVideoDecodeEnabled()) { | 1358 if (IsAcceleratedVideoDecodeEnabled()) { |
1370 const char kI965DrvVideoPath_64[] = | 1359 const char kI965DrvVideoPath_64[] = |
1371 "/usr/lib64/va/drivers/i965_drv_video.so"; | 1360 "/usr/lib64/va/drivers/i965_drv_video.so"; |
1372 dlopen(kI965DrvVideoPath_64, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); | 1361 dlopen(kI965DrvVideoPath_64, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE); |
1373 } | 1362 } |
1374 } | 1363 } |
1375 #endif | 1364 #endif |
(...skipping 26 matching lines...) Expand all Loading... |
1402 | 1391 |
1403 if (process_type == switches::kUtilityProcess) { | 1392 if (process_type == switches::kUtilityProcess) { |
1404 return BlacklistDebugAndNumaPolicy; | 1393 return BlacklistDebugAndNumaPolicy; |
1405 } | 1394 } |
1406 | 1395 |
1407 NOTREACHED(); | 1396 NOTREACHED(); |
1408 // This will be our default if we need one. | 1397 // This will be our default if we need one. |
1409 return AllowAllPolicy; | 1398 return AllowAllPolicy; |
1410 } | 1399 } |
1411 | 1400 |
| 1401 // broker_process can be NULL if there is no need for one. |
| 1402 void StartSandboxWithPolicy(Sandbox::EvaluateSyscall syscall_policy, |
| 1403 BrokerProcess* broker_process) { |
| 1404 |
| 1405 Sandbox::setSandboxPolicy(syscall_policy, broker_process); |
| 1406 Sandbox::startSandbox(); |
| 1407 } |
| 1408 |
1412 // Initialize the seccomp-bpf sandbox. | 1409 // Initialize the seccomp-bpf sandbox. |
1413 bool StartBpfSandbox(const CommandLine& command_line, | 1410 bool StartBpfSandbox(const CommandLine& command_line, |
1414 const std::string& process_type) { | 1411 const std::string& process_type) { |
1415 Sandbox::EvaluateSyscall SyscallPolicy = | 1412 Sandbox::EvaluateSyscall syscall_policy = |
1416 GetProcessSyscallPolicy(command_line, process_type); | 1413 GetProcessSyscallPolicy(command_line, process_type); |
1417 | 1414 |
1418 // Warms up resources needed by the policy we're about to enable. | 1415 BrokerProcess* broker_process = NULL; |
1419 WarmupPolicy(SyscallPolicy); | 1416 // Warm up resources needed by the policy we're about to enable and |
| 1417 // eventually start a broker process. |
| 1418 WarmupPolicy(syscall_policy, &broker_process); |
1420 | 1419 |
1421 Sandbox::setSandboxPolicy(SyscallPolicy, NULL); | 1420 StartSandboxWithPolicy(syscall_policy, broker_process); |
1422 Sandbox::startSandbox(); | |
1423 | 1421 |
1424 return true; | 1422 return true; |
1425 } | 1423 } |
1426 | 1424 |
1427 } // namespace | 1425 } // namespace |
1428 | 1426 |
1429 #endif // SECCOMP_BPF_SANDBOX | 1427 #endif // SECCOMP_BPF_SANDBOX |
1430 | 1428 |
1431 namespace content { | 1429 namespace content { |
1432 | 1430 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 // should enable it, enable it or die. | 1479 // should enable it, enable it or die. |
1482 bool started_sandbox = StartBpfSandbox(command_line, process_type); | 1480 bool started_sandbox = StartBpfSandbox(command_line, process_type); |
1483 CHECK(started_sandbox); | 1481 CHECK(started_sandbox); |
1484 return true; | 1482 return true; |
1485 } | 1483 } |
1486 #endif | 1484 #endif |
1487 return false; | 1485 return false; |
1488 } | 1486 } |
1489 | 1487 |
1490 } // namespace content | 1488 } // namespace content |
OLD | NEW |