Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(537)

Side by Side Diff: sandbox/linux/seccomp/sandbox.cc

Issue 371047: Allow the seccomp sandbox to be enabled, even if the suid sandbox has... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/seccomp/sandbox.h ('k') | sandbox/linux/seccomp/sandbox_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #include "library.h" 1 #include "library.h"
2 #include "sandbox_impl.h" 2 #include "sandbox_impl.h"
3 #include "syscall_table.h" 3 #include "syscall_table.h"
4 4
5 namespace playground { 5 namespace playground {
6 6
7 // Global variables 7 // Global variables
8 int Sandbox::proc_self_maps_ = -1;
8 enum Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 9 enum Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
9 int Sandbox::pid_; 10 int Sandbox::pid_;
10 int Sandbox::processFdPub_; 11 int Sandbox::processFdPub_;
11 int Sandbox::cloneFdPub_; 12 int Sandbox::cloneFdPub_;
12 Sandbox::ProtectedMap Sandbox::protectedMap_; 13 Sandbox::ProtectedMap Sandbox::protectedMap_;
13 std::vector<SecureMem::Args*> Sandbox::secureMemPool_; 14 std::vector<SecureMem::Args*> Sandbox::secureMemPool_;
14 15
15 bool Sandbox::sendFd(int transport, int fd0, int fd1, const void* buf, 16 bool Sandbox::sendFd(int transport, int fd0, int fd1, const void* buf,
16 size_t len) { 17 size_t len) {
17 int fds[2], count = 0; 18 int fds[2], count = 0;
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 : "memory" 334 : "memory"
334 #if defined(__x86_64__) 335 #if defined(__x86_64__)
335 , "rsp" 336 , "rsp"
336 #elif defined(__i386__) 337 #elif defined(__i386__)
337 , "esp" 338 , "esp"
338 #endif 339 #endif
339 ); 340 );
340 return fnc; 341 return fnc;
341 } 342 }
342 343
343 void Sandbox::snapshotMemoryMappings(int processFd) { 344 void Sandbox::snapshotMemoryMappings(int processFd, int proc_self_maps) {
344 SysCalls sys; 345 SysCalls sys;
345 int mapsFd = sys.open("/proc/self/maps", O_RDONLY, 0); 346 if (sys.lseek(proc_self_maps, 0, SEEK_SET) ||
346 if (mapsFd < 0 || !sendFd(processFd, mapsFd, -1, NULL, 0)) { 347 !sendFd(processFd, proc_self_maps, -1, NULL, 0)) {
347 failure: 348 failure:
348 die("Cannot access /proc/self/maps"); 349 die("Cannot access /proc/self/maps");
349 } 350 }
350 NOINTR_SYS(sys.close(mapsFd));
351 int dummy; 351 int dummy;
352 if (read(sys, processFd, &dummy, sizeof(dummy)) != sizeof(dummy)) { 352 if (read(sys, processFd, &dummy, sizeof(dummy)) != sizeof(dummy)) {
353 goto failure; 353 goto failure;
354 } 354 }
355 } 355 }
356 356
357 int Sandbox::supportsSeccompSandbox() { 357 int Sandbox::supportsSeccompSandbox(int proc_fd) {
358 if (status_ != STATUS_UNKNOWN) { 358 if (status_ != STATUS_UNKNOWN) {
359 return status_ != STATUS_UNSUPPORTED; 359 return status_ != STATUS_UNSUPPORTED;
360 } 360 }
361 int fds[2]; 361 int fds[2];
362 SysCalls sys; 362 SysCalls sys;
363 if (sys.pipe(fds)) { 363 if (sys.pipe(fds)) {
364 status_ = STATUS_UNSUPPORTED; 364 status_ = STATUS_UNSUPPORTED;
365 return 0; 365 return 0;
366 } 366 }
367 pid_t pid; 367 pid_t pid;
368 switch ((pid = sys.fork())) { 368 switch ((pid = sys.fork())) {
369 case -1: 369 case -1:
370 status_ = STATUS_UNSUPPORTED; 370 status_ = STATUS_UNSUPPORTED;
371 return 0; 371 return 0;
372 case 0: { 372 case 0: {
373 int devnull = sys.open("/dev/null", O_RDWR, 0); 373 int devnull = sys.open("/dev/null", O_RDWR, 0);
374 if (devnull >= 0) { 374 if (devnull >= 0) {
375 dup2(devnull, 0); 375 dup2(devnull, 0);
376 dup2(devnull, 1); 376 dup2(devnull, 1);
377 dup2(devnull, 2); 377 dup2(devnull, 2);
378 } 378 }
379 if (proc_fd >= 0) {
380 setProcSelfMaps(sys.openat(proc_fd, "self/maps", O_RDONLY, 0));
381 }
379 startSandbox(); 382 startSandbox();
380 write(sys, fds[1], "", 1); 383 write(sys, fds[1], "", 1);
381 _exit(0); 384
382 sys.exit_group(0); 385 // Try to tell the trusted thread to shut down the entire process in an
386 // orderly fashion
387 defaultSystemCallHandler(__NR_exit_group, 0, 0, 0, 0, 0, 0);
388
389 // If that did not work (e.g. because the kernel does not know about the
390 // exit_group() system call), make a direct _exit() system call instead.
391 // This system call is unrestricted in seccomp mode, so it will always
392 // succeed. Normally, we don't like it, because unlike exit_group() it
393 // does not terminate any other thread. But since we know that
394 // exit_group() exists in all kernels which support kernel-level threads,
395 // this is OK we only get here for old kernels where _exit() is OK.
383 sys._exit(0); 396 sys._exit(0);
384 } 397 }
385 default: 398 default:
386 NOINTR_SYS(sys.close(fds[1])); 399 NOINTR_SYS(sys.close(fds[1]));
387 char ch; 400 char ch;
388 if (read(sys, fds[0], &ch, 1) != 1) { 401 if (read(sys, fds[0], &ch, 1) != 1) {
389 status_ = STATUS_UNSUPPORTED; 402 status_ = STATUS_UNSUPPORTED;
390 } else { 403 } else {
391 status_ = STATUS_AVAILABLE; 404 status_ = STATUS_AVAILABLE;
392 } 405 }
393 int rc; 406 int rc;
394 NOINTR_SYS(sys.waitpid(pid, &rc, 0)); 407 NOINTR_SYS(sys.waitpid(pid, &rc, 0));
395 NOINTR_SYS(sys.close(fds[0])); 408 NOINTR_SYS(sys.close(fds[0]));
396 return status_ != STATUS_UNSUPPORTED; 409 return status_ != STATUS_UNSUPPORTED;
397 } 410 }
398 } 411 }
399 412
413 void Sandbox::setProcSelfMaps(int proc_self_maps) {
414 proc_self_maps_ = proc_self_maps;
415 }
416
400 void Sandbox::startSandbox() { 417 void Sandbox::startSandbox() {
401 if (status_ == STATUS_UNSUPPORTED) { 418 if (status_ == STATUS_UNSUPPORTED) {
402 die("The seccomp sandbox is not supported on this computer"); 419 die("The seccomp sandbox is not supported on this computer");
403 } else if (status_ == STATUS_ENABLED) { 420 } else if (status_ == STATUS_ENABLED) {
404 return; 421 return;
405 } 422 }
406 423
407 SysCalls sys; 424 SysCalls sys;
425 if (proc_self_maps_ < 0) {
426 proc_self_maps_ = sys.open("/proc/self/maps", O_RDONLY, 0);
427 if (proc_self_maps_ < 0) {
428 die("Cannot access \"/proc/self/maps\"");
429 }
430 }
408 431
409 // The pid is unchanged for the entire program, so we can retrieve it once 432 // The pid is unchanged for the entire program, so we can retrieve it once
410 // and store it in a global variable. 433 // and store it in a global variable.
411 pid_ = sys.getpid(); 434 pid_ = sys.getpid();
412 435
413 // Block all signals, except for the RDTSC handler 436 // Block all signals, except for the RDTSC handler
414 setupSignalHandlers(); 437 setupSignalHandlers();
415 438
416 // Get socketpairs for talking to the trusted process 439 // Get socketpairs for talking to the trusted process
417 int pair[4]; 440 int pair[4];
418 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) || 441 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) ||
419 socketpair(AF_UNIX, SOCK_STREAM, 0, pair+2)) { 442 socketpair(AF_UNIX, SOCK_STREAM, 0, pair+2)) {
420 die("Failed to create trusted thread"); 443 die("Failed to create trusted thread");
421 } 444 }
422 processFdPub_ = pair[0]; 445 processFdPub_ = pair[0];
423 cloneFdPub_ = pair[2]; 446 cloneFdPub_ = pair[2];
424 SecureMemArgs::Args* secureMem = createTrustedProcess(pair[0], pair[1], 447 SecureMemArgs::Args* secureMem = createTrustedProcess(pair[0], pair[1],
425 pair[2], pair[3]); 448 pair[2], pair[3]);
426 449
427 // We find all libraries that have system calls and redirect the system 450 // We find all libraries that have system calls and redirect the system
428 // calls to the sandbox. If we miss any system calls, the application will be 451 // calls to the sandbox. If we miss any system calls, the application will be
429 // terminated by the kernel's seccomp code. So, from a security point of 452 // terminated by the kernel's seccomp code. So, from a security point of
430 // view, if this code fails to identify system calls, we are still behaving 453 // view, if this code fails to identify system calls, we are still behaving
431 // correctly. 454 // correctly.
432 { 455 {
433 Maps maps("/proc/self/maps"); 456 Maps maps(proc_self_maps_);
434 const char *libs[] = { "ld", "libc", "librt", "libpthread", NULL }; 457 const char *libs[] = { "ld", "libc", "librt", "libpthread", NULL };
435 458
436 // Intercept system calls in the VDSO segment (if any). This has to happen 459 // Intercept system calls in the VDSO segment (if any). This has to happen
437 // before intercepting system calls in any of the other libraries, as 460 // before intercepting system calls in any of the other libraries, as
438 // the main kernel entry point might be inside of the VDSO and we need to 461 // the main kernel entry point might be inside of the VDSO and we need to
439 // determine its address before we can compare it to jumps from inside 462 // determine its address before we can compare it to jumps from inside
440 // other libraries. 463 // other libraries.
441 for (Maps::const_iterator iter = maps.begin(); iter != maps.end(); ++iter){ 464 for (Maps::const_iterator iter = maps.begin(); iter != maps.end(); ++iter){
442 Library* library = *iter; 465 Library* library = *iter;
443 if (library->isVDSO() && library->parseElf()) { 466 if (library->isVDSO() && library->parseElf()) {
(...skipping 19 matching lines...) Expand all
463 break; 486 break;
464 } 487 }
465 } 488 }
466 } 489 }
467 } 490 }
468 } 491 }
469 } 492 }
470 493
471 // Take a snapshot of the current memory mappings. These mappings will be 494 // Take a snapshot of the current memory mappings. These mappings will be
472 // off-limits to all future mmap(), munmap(), mremap(), and mprotect() calls. 495 // off-limits to all future mmap(), munmap(), mremap(), and mprotect() calls.
473 snapshotMemoryMappings(processFdPub_); 496 snapshotMemoryMappings(processFdPub_, proc_self_maps_);
497 NOINTR_SYS(sys.close(proc_self_maps_));
498 proc_self_maps_ = -1;
474 499
475 // Creating the trusted thread enables sandboxing 500 // Creating the trusted thread enables sandboxing
476 createTrustedThread(processFdPub_, cloneFdPub_, secureMem); 501 createTrustedThread(processFdPub_, cloneFdPub_, secureMem);
477 502
478 // We can no longer check for sandboxing support at this point, but we also 503 // We can no longer check for sandboxing support at this point, but we also
479 // know for a fact that it is available (as we just turned it on). So update 504 // know for a fact that it is available (as we just turned it on). So update
480 // the status to reflect this information. 505 // the status to reflect this information.
481 status_ = STATUS_ENABLED; 506 status_ = STATUS_ENABLED;
482 } 507 }
483 508
484 } // namespace 509 } // namespace
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp/sandbox.h ('k') | sandbox/linux/seccomp/sandbox_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698