| 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 "content/public/common/sandbox_init.h" | 5 #include "content/public/common/sandbox_init.h" |
| 6 | 6 |
| 7 #if defined(__i386__) || defined(__x86_64__) | 7 #if defined(__i386__) || defined(__x86_64__) |
| 8 | 8 |
| 9 // This is an assert for GYP | 9 // This is an assert for GYP |
| 10 #if !defined(OS_LINUX) | 10 #if !defined(OS_LINUX) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 #ifndef __NR_process_vm_readv | 49 #ifndef __NR_process_vm_readv |
| 50 #define __NR_process_vm_readv 347 | 50 #define __NR_process_vm_readv 347 |
| 51 #endif | 51 #endif |
| 52 | 52 |
| 53 #ifndef __NR_process_vm_writev | 53 #ifndef __NR_process_vm_writev |
| 54 #define __NR_process_vm_writev 348 | 54 #define __NR_process_vm_writev 348 |
| 55 #endif | 55 #endif |
| 56 | 56 |
| 57 #endif | 57 #endif |
| 58 | 58 |
| 59 using playground2::arch_seccomp_data; |
| 60 using playground2::ErrorCode; |
| 61 using playground2::Sandbox; |
| 62 |
| 59 namespace { | 63 namespace { |
| 60 | 64 |
| 61 bool IsSingleThreaded() { | 65 bool IsSingleThreaded() { |
| 62 // Possibly racy, but it's ok because this is more of a debug check to catch | 66 // Possibly racy, but it's ok because this is more of a debug check to catch |
| 63 // new threaded situations arising during development. | 67 // new threaded situations arising during development. |
| 64 int num_threads = | 68 int num_threads = |
| 65 file_util::CountFilesCreatedAfter(FilePath("/proc/self/task"), | 69 file_util::CountFilesCreatedAfter(FilePath("/proc/self/task"), |
| 66 base::Time::UnixEpoch()); | 70 base::Time::UnixEpoch()); |
| 67 | 71 |
| 68 // We pass the test if we don't know ( == 0), because the setuid sandbox | 72 // We pass the test if we don't know ( == 0), because the setuid sandbox |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 if (strcmp(pathname, kDriRcPath) == 0) { | 213 if (strcmp(pathname, kDriRcPath) == 0) { |
| 210 int ret = OpenWithCache(pathname, flags); | 214 int ret = OpenWithCache(pathname, flags); |
| 211 return (ret == -1) ? -errno : ret; | 215 return (ret == -1) ? -errno : ret; |
| 212 } else { | 216 } else { |
| 213 return -ENOENT; | 217 return -ENOENT; |
| 214 } | 218 } |
| 215 } | 219 } |
| 216 | 220 |
| 217 #if defined(__x86_64__) | 221 #if defined(__x86_64__) |
| 218 // x86_64 only because it references system calls that are multiplexed on IA32. | 222 // x86_64 only because it references system calls that are multiplexed on IA32. |
| 219 playground2::Sandbox::ErrorCode GpuProcessPolicy_x86_64(int sysno) { | 223 ErrorCode GpuProcessPolicy_x86_64(int sysno) { |
| 220 switch(sysno) { | 224 switch(sysno) { |
| 221 case __NR_read: | 225 case __NR_read: |
| 222 case __NR_ioctl: | 226 case __NR_ioctl: |
| 223 case __NR_poll: | 227 case __NR_poll: |
| 224 case __NR_epoll_wait: | 228 case __NR_epoll_wait: |
| 225 case __NR_recvfrom: | 229 case __NR_recvfrom: |
| 226 case __NR_write: | 230 case __NR_write: |
| 227 case __NR_writev: | 231 case __NR_writev: |
| 228 case __NR_gettid: | 232 case __NR_gettid: |
| 229 case __NR_sched_yield: // Nvidia binary driver. | 233 case __NR_sched_yield: // Nvidia binary driver. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 257 case __NR_dup: | 261 case __NR_dup: |
| 258 case __NR_mlock: | 262 case __NR_mlock: |
| 259 case __NR_munlock: | 263 case __NR_munlock: |
| 260 case __NR_exit: | 264 case __NR_exit: |
| 261 case __NR_exit_group: | 265 case __NR_exit_group: |
| 262 case __NR_lseek: | 266 case __NR_lseek: |
| 263 case __NR_getpid: // Nvidia binary driver. | 267 case __NR_getpid: // Nvidia binary driver. |
| 264 case __NR_getppid: // ATI binary driver. | 268 case __NR_getppid: // ATI binary driver. |
| 265 case __NR_shutdown: // Virtual driver. | 269 case __NR_shutdown: // Virtual driver. |
| 266 case __NR_rt_sigaction: // Breakpad signal handler. | 270 case __NR_rt_sigaction: // Breakpad signal handler. |
| 267 return playground2::Sandbox::SB_ALLOWED; | 271 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 268 case __NR_socket: | 272 case __NR_socket: |
| 269 return EACCES; // Nvidia binary driver. | 273 return ErrorCode(EACCES); // Nvidia binary driver. |
| 270 case __NR_fchmod: | 274 case __NR_fchmod: |
| 271 return EPERM; // ATI binary driver. | 275 return ErrorCode(EPERM); // ATI binary driver. |
| 272 case __NR_open: | 276 case __NR_open: |
| 273 // Hook open() in the GPU process to allow opening /etc/drirc, | 277 // Hook open() in the GPU process to allow opening /etc/drirc, |
| 274 // needed by Mesa. | 278 // needed by Mesa. |
| 275 // The hook needs dup(), lseek(), and close() to be allowed. | 279 // The hook needs dup(), lseek(), and close() to be allowed. |
| 276 return playground2::Sandbox::ErrorCode(GpuOpenSIGSYS_Handler, NULL); | 280 return Sandbox::Trap(GpuOpenSIGSYS_Handler, NULL); |
| 277 default: | 281 default: |
| 278 if (IsGettimeSyscall(sysno) || | 282 if (IsGettimeSyscall(sysno) || |
| 279 IsKillSyscall(sysno)) { // GPU watchdog. | 283 IsKillSyscall(sysno)) { // GPU watchdog. |
| 280 return playground2::Sandbox::SB_ALLOWED; | 284 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 281 } | 285 } |
| 282 // Generally, filename-based syscalls will fail with ENOENT to behave | 286 // Generally, filename-based syscalls will fail with ENOENT to behave |
| 283 // similarly to a possible future setuid sandbox. | 287 // similarly to a possible future setuid sandbox. |
| 284 if (IsFileSystemSyscall(sysno)) { | 288 if (IsFileSystemSyscall(sysno)) { |
| 285 return ENOENT; | 289 return ErrorCode(ENOENT); |
| 286 } | 290 } |
| 287 // In any other case crash the program with our SIGSYS handler | 291 // In any other case crash the program with our SIGSYS handler |
| 288 return playground2::Sandbox::ErrorCode(CrashSIGSYS_Handler, NULL); | 292 return Sandbox::Trap(CrashSIGSYS_Handler, NULL); |
| 289 } | 293 } |
| 290 } | 294 } |
| 291 | 295 |
| 292 // x86_64 only because it references system calls that are multiplexed on IA32. | 296 // x86_64 only because it references system calls that are multiplexed on IA32. |
| 293 playground2::Sandbox::ErrorCode FlashProcessPolicy_x86_64(int sysno) { | 297 ErrorCode FlashProcessPolicy_x86_64(int sysno) { |
| 294 switch (sysno) { | 298 switch (sysno) { |
| 295 case __NR_futex: | 299 case __NR_futex: |
| 296 case __NR_write: | 300 case __NR_write: |
| 297 case __NR_epoll_wait: | 301 case __NR_epoll_wait: |
| 298 case __NR_read: | 302 case __NR_read: |
| 299 case __NR_times: | 303 case __NR_times: |
| 300 case __NR_clone: // TODO(jln): restrict flags. | 304 case __NR_clone: // TODO(jln): restrict flags. |
| 301 case __NR_set_robust_list: | 305 case __NR_set_robust_list: |
| 302 case __NR_getuid: | 306 case __NR_getuid: |
| 303 case __NR_geteuid: | 307 case __NR_geteuid: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 329 case __NR_brk: | 333 case __NR_brk: |
| 330 case __NR_sched_yield: | 334 case __NR_sched_yield: |
| 331 case __NR_shutdown: | 335 case __NR_shutdown: |
| 332 case __NR_sched_getaffinity: | 336 case __NR_sched_getaffinity: |
| 333 case __NR_sched_setscheduler: | 337 case __NR_sched_setscheduler: |
| 334 case __NR_dup: // Flash Access. | 338 case __NR_dup: // Flash Access. |
| 335 // These are under investigation, and hopefully not here for the long term. | 339 // These are under investigation, and hopefully not here for the long term. |
| 336 case __NR_shmctl: | 340 case __NR_shmctl: |
| 337 case __NR_shmat: | 341 case __NR_shmat: |
| 338 case __NR_shmdt: | 342 case __NR_shmdt: |
| 339 return playground2::Sandbox::SB_ALLOWED; | 343 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 340 case __NR_ioctl: | 344 case __NR_ioctl: |
| 341 return ENOTTY; // Flash Access. | 345 return ErrorCode(ENOTTY); // Flash Access. |
| 342 case __NR_socket: | 346 case __NR_socket: |
| 343 return EACCES; | 347 return ErrorCode(EACCES); |
| 344 | 348 |
| 345 default: | 349 default: |
| 346 if (IsGettimeSyscall(sysno) || | 350 if (IsGettimeSyscall(sysno) || |
| 347 IsKillSyscall(sysno)) { | 351 IsKillSyscall(sysno)) { |
| 348 return playground2::Sandbox::SB_ALLOWED; | 352 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 349 } | 353 } |
| 350 if (IsFileSystemSyscall(sysno)) { | 354 if (IsFileSystemSyscall(sysno)) { |
| 351 return ENOENT; | 355 return ErrorCode(ENOENT); |
| 352 } | 356 } |
| 353 // In any other case crash the program with our SIGSYS handler. | 357 // In any other case crash the program with our SIGSYS handler. |
| 354 return playground2::Sandbox::ErrorCode(CrashSIGSYS_Handler, NULL); | 358 return Sandbox::Trap(CrashSIGSYS_Handler, NULL); |
| 355 } | 359 } |
| 356 } | 360 } |
| 357 #endif | 361 #endif |
| 358 | 362 |
| 359 playground2::Sandbox::ErrorCode BlacklistPtracePolicy(int sysno) { | 363 ErrorCode BlacklistPtracePolicy(int sysno) { |
| 360 if (sysno < static_cast<int>(MIN_SYSCALL) || | 364 if (sysno < static_cast<int>(MIN_SYSCALL) || |
| 361 sysno > static_cast<int>(MAX_SYSCALL)) { | 365 sysno > static_cast<int>(MAX_SYSCALL)) { |
| 362 // TODO(jln) we should not have to do that in a trivial policy. | 366 // TODO(jln) we should not have to do that in a trivial policy. |
| 363 return ENOSYS; | 367 return ErrorCode(ENOSYS); |
| 364 } | 368 } |
| 365 switch (sysno) { | 369 switch (sysno) { |
| 366 case __NR_ptrace: | 370 case __NR_ptrace: |
| 367 case __NR_process_vm_readv: | 371 case __NR_process_vm_readv: |
| 368 case __NR_process_vm_writev: | 372 case __NR_process_vm_writev: |
| 369 case __NR_migrate_pages: | 373 case __NR_migrate_pages: |
| 370 case __NR_move_pages: | 374 case __NR_move_pages: |
| 371 return playground2::Sandbox::ErrorCode(CrashSIGSYS_Handler, NULL); | 375 return Sandbox::Trap(CrashSIGSYS_Handler, NULL); |
| 372 default: | 376 default: |
| 373 return playground2::Sandbox::SB_ALLOWED; | 377 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 374 } | 378 } |
| 375 } | 379 } |
| 376 | 380 |
| 377 // Allow all syscalls. | 381 // Allow all syscalls. |
| 378 // This will still deny x32 or IA32 calls in 64 bits mode or | 382 // This will still deny x32 or IA32 calls in 64 bits mode or |
| 379 // 64 bits system calls in compatibility mode. | 383 // 64 bits system calls in compatibility mode. |
| 380 playground2::Sandbox::ErrorCode AllowAllPolicy(int sysno) { | 384 ErrorCode AllowAllPolicy(int sysno) { |
| 381 if (sysno < static_cast<int>(MIN_SYSCALL) || | 385 if (sysno < static_cast<int>(MIN_SYSCALL) || |
| 382 sysno > static_cast<int>(MAX_SYSCALL)) { | 386 sysno > static_cast<int>(MAX_SYSCALL)) { |
| 383 // TODO(jln) we should not have to do that in a trivial policy. | 387 // TODO(jln) we should not have to do that in a trivial policy. |
| 384 return ENOSYS; | 388 return ErrorCode(ENOSYS); |
| 385 } else { | 389 } else { |
| 386 return playground2::Sandbox::SB_ALLOWED; | 390 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 387 } | 391 } |
| 388 } | 392 } |
| 389 | 393 |
| 390 // Warms up/preloads resources needed by the policies. | 394 // Warms up/preloads resources needed by the policies. |
| 391 void WarmupPolicy(playground2::Sandbox::EvaluateSyscall policy) { | 395 void WarmupPolicy(Sandbox::EvaluateSyscall policy) { |
| 392 #if defined(__x86_64__) | 396 #if defined(__x86_64__) |
| 393 if (policy == GpuProcessPolicy_x86_64) | 397 if (policy == GpuProcessPolicy_x86_64) |
| 394 OpenWithCache(kDriRcPath, O_RDONLY); | 398 OpenWithCache(kDriRcPath, O_RDONLY); |
| 395 #endif | 399 #endif |
| 396 } | 400 } |
| 397 | 401 |
| 398 // Is the sandbox fully disabled for this process? | 402 // Is the sandbox fully disabled for this process? |
| 399 bool ShouldDisableSandbox(const CommandLine& command_line, | 403 bool ShouldDisableSandbox(const CommandLine& command_line, |
| 400 const std::string& process_type) { | 404 const std::string& process_type) { |
| 401 if (command_line.HasSwitch(switches::kNoSandbox) || | 405 if (command_line.HasSwitch(switches::kNoSandbox) || |
| (...skipping 17 matching lines...) Expand all Loading... |
| 419 if (command_line.HasSwitch(switches::kEnableGpuSandbox)) | 423 if (command_line.HasSwitch(switches::kEnableGpuSandbox)) |
| 420 should_disable = false; | 424 should_disable = false; |
| 421 if (command_line.HasSwitch(switches::kDisableGpuSandbox)) | 425 if (command_line.HasSwitch(switches::kDisableGpuSandbox)) |
| 422 should_disable = true; | 426 should_disable = true; |
| 423 return should_disable; | 427 return should_disable; |
| 424 } | 428 } |
| 425 | 429 |
| 426 return false; | 430 return false; |
| 427 } | 431 } |
| 428 | 432 |
| 429 playground2::Sandbox::EvaluateSyscall GetProcessSyscallPolicy( | 433 Sandbox::EvaluateSyscall GetProcessSyscallPolicy( |
| 430 const CommandLine& command_line, | 434 const CommandLine& command_line, |
| 431 const std::string& process_type) { | 435 const std::string& process_type) { |
| 432 #if defined(__x86_64__) | 436 #if defined(__x86_64__) |
| 433 if (process_type == switches::kGpuProcess) { | 437 if (process_type == switches::kGpuProcess) { |
| 434 return GpuProcessPolicy_x86_64; | 438 return GpuProcessPolicy_x86_64; |
| 435 } | 439 } |
| 436 | 440 |
| 437 if (process_type == switches::kPpapiPluginProcess) { | 441 if (process_type == switches::kPpapiPluginProcess) { |
| 438 // TODO(jln): figure out what to do with non-Flash PPAPI | 442 // TODO(jln): figure out what to do with non-Flash PPAPI |
| 439 // out-of-process plug-ins. | 443 // out-of-process plug-ins. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 VLOG(1) << "Seccomp BPF disabled in " | 492 VLOG(1) << "Seccomp BPF disabled in " |
| 489 << process_type | 493 << process_type |
| 490 << " because seccomp mode 1 is enabled."; | 494 << " because seccomp mode 1 is enabled."; |
| 491 return; | 495 return; |
| 492 } | 496 } |
| 493 | 497 |
| 494 // TODO(jln): find a way for the Zygote processes under the setuid sandbox to | 498 // TODO(jln): find a way for the Zygote processes under the setuid sandbox to |
| 495 // have a /proc fd and pass it here. | 499 // have a /proc fd and pass it here. |
| 496 // Passing -1 as the /proc fd since we have no special way to have it for | 500 // Passing -1 as the /proc fd since we have no special way to have it for |
| 497 // now. | 501 // now. |
| 498 if (playground2::Sandbox::supportsSeccompSandbox(-1) != | 502 if (Sandbox::supportsSeccompSandbox(-1) != |
| 499 playground2::Sandbox::STATUS_AVAILABLE) { | 503 Sandbox::STATUS_AVAILABLE) { |
| 500 return; | 504 return; |
| 501 } | 505 } |
| 502 | 506 |
| 503 playground2::Sandbox::EvaluateSyscall SyscallPolicy = | 507 Sandbox::EvaluateSyscall SyscallPolicy = |
| 504 GetProcessSyscallPolicy(command_line, process_type); | 508 GetProcessSyscallPolicy(command_line, process_type); |
| 505 | 509 |
| 506 // Warms up resources needed by the policy we're about to enable. | 510 // Warms up resources needed by the policy we're about to enable. |
| 507 WarmupPolicy(SyscallPolicy); | 511 WarmupPolicy(SyscallPolicy); |
| 508 | 512 |
| 509 playground2::Sandbox::setSandboxPolicy(SyscallPolicy, NULL); | 513 Sandbox::setSandboxPolicy(SyscallPolicy, NULL); |
| 510 playground2::Sandbox::startSandbox(); | 514 Sandbox::startSandbox(); |
| 511 | 515 |
| 512 // TODO(jorgelo): remove this once we surface | 516 // TODO(jorgelo): remove this once we surface |
| 513 // seccomp filter sandbox status in about:sandbox. | 517 // seccomp filter sandbox status in about:sandbox. |
| 514 const std::string ActivatedSeccomp = | 518 const std::string ActivatedSeccomp = |
| 515 "Activated seccomp filter sandbox for process type: " + | 519 "Activated seccomp filter sandbox for process type: " + |
| 516 process_type + "."; | 520 process_type + "."; |
| 517 if (IsChromeOS()) | 521 if (IsChromeOS()) |
| 518 LOG(WARNING) << ActivatedSeccomp; | 522 LOG(WARNING) << ActivatedSeccomp; |
| 519 else | 523 else |
| 520 VLOG(1) << ActivatedSeccomp; | 524 VLOG(1) << ActivatedSeccomp; |
| 521 } | 525 } |
| 522 | 526 |
| 523 } // anonymous namespace | 527 } // anonymous namespace |
| 524 | 528 |
| 525 #endif // defined(__i386__) || defined(__x86_64__) | 529 #endif // defined(__i386__) || defined(__x86_64__) |
| 526 | 530 |
| 527 namespace content { | 531 namespace content { |
| 528 | 532 |
| 529 void InitializeSandbox() { | 533 void InitializeSandbox() { |
| 530 #if defined(__i386__) || defined(__x86_64__) | 534 #if defined(__i386__) || defined(__x86_64__) |
| 531 InitializeSandbox_x86(); | 535 InitializeSandbox_x86(); |
| 532 #endif | 536 #endif |
| 533 } | 537 } |
| 534 | 538 |
| 535 } // namespace content | 539 } // namespace content |
| OLD | NEW |