| Index: sandbox/linux/seccomp/sandbox.cc
|
| ===================================================================
|
| --- sandbox/linux/seccomp/sandbox.cc (revision 31339)
|
| +++ sandbox/linux/seccomp/sandbox.cc (working copy)
|
| @@ -5,6 +5,7 @@
|
| namespace playground {
|
|
|
| // Global variables
|
| +int Sandbox::proc_self_maps_ = -1;
|
| enum Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
|
| int Sandbox::pid_;
|
| int Sandbox::processFdPub_;
|
| @@ -340,21 +341,20 @@
|
| return fnc;
|
| }
|
|
|
| -void Sandbox::snapshotMemoryMappings(int processFd) {
|
| +void Sandbox::snapshotMemoryMappings(int processFd, int proc_self_maps) {
|
| SysCalls sys;
|
| - int mapsFd = sys.open("/proc/self/maps", O_RDONLY, 0);
|
| - if (mapsFd < 0 || !sendFd(processFd, mapsFd, -1, NULL, 0)) {
|
| + if (sys.lseek(proc_self_maps, 0, SEEK_SET) ||
|
| + !sendFd(processFd, proc_self_maps, -1, NULL, 0)) {
|
| failure:
|
| die("Cannot access /proc/self/maps");
|
| }
|
| - NOINTR_SYS(sys.close(mapsFd));
|
| int dummy;
|
| if (read(sys, processFd, &dummy, sizeof(dummy)) != sizeof(dummy)) {
|
| goto failure;
|
| }
|
| }
|
|
|
| -int Sandbox::supportsSeccompSandbox() {
|
| +int Sandbox::supportsSeccompSandbox(int proc_fd) {
|
| if (status_ != STATUS_UNKNOWN) {
|
| return status_ != STATUS_UNSUPPORTED;
|
| }
|
| @@ -376,10 +376,23 @@
|
| dup2(devnull, 1);
|
| dup2(devnull, 2);
|
| }
|
| + if (proc_fd >= 0) {
|
| + setProcSelfMaps(sys.openat(proc_fd, "self/maps", O_RDONLY, 0));
|
| + }
|
| startSandbox();
|
| write(sys, fds[1], "", 1);
|
| - _exit(0);
|
| - sys.exit_group(0);
|
| +
|
| + // Try to tell the trusted thread to shut down the entire process in an
|
| + // orderly fashion
|
| + defaultSystemCallHandler(__NR_exit_group, 0, 0, 0, 0, 0, 0);
|
| +
|
| + // If that did not work (e.g. because the kernel does not know about the
|
| + // exit_group() system call), make a direct _exit() system call instead.
|
| + // This system call is unrestricted in seccomp mode, so it will always
|
| + // succeed. Normally, we don't like it, because unlike exit_group() it
|
| + // does not terminate any other thread. But since we know that
|
| + // exit_group() exists in all kernels which support kernel-level threads,
|
| + // this is OK we only get here for old kernels where _exit() is OK.
|
| sys._exit(0);
|
| }
|
| default:
|
| @@ -397,6 +410,10 @@
|
| }
|
| }
|
|
|
| +void Sandbox::setProcSelfMaps(int proc_self_maps) {
|
| + proc_self_maps_ = proc_self_maps;
|
| +}
|
| +
|
| void Sandbox::startSandbox() {
|
| if (status_ == STATUS_UNSUPPORTED) {
|
| die("The seccomp sandbox is not supported on this computer");
|
| @@ -405,6 +422,12 @@
|
| }
|
|
|
| SysCalls sys;
|
| + if (proc_self_maps_ < 0) {
|
| + proc_self_maps_ = sys.open("/proc/self/maps", O_RDONLY, 0);
|
| + if (proc_self_maps_ < 0) {
|
| + die("Cannot access \"/proc/self/maps\"");
|
| + }
|
| + }
|
|
|
| // The pid is unchanged for the entire program, so we can retrieve it once
|
| // and store it in a global variable.
|
| @@ -430,7 +453,7 @@
|
| // view, if this code fails to identify system calls, we are still behaving
|
| // correctly.
|
| {
|
| - Maps maps("/proc/self/maps");
|
| + Maps maps(proc_self_maps_);
|
| const char *libs[] = { "ld", "libc", "librt", "libpthread", NULL };
|
|
|
| // Intercept system calls in the VDSO segment (if any). This has to happen
|
| @@ -470,7 +493,9 @@
|
|
|
| // Take a snapshot of the current memory mappings. These mappings will be
|
| // off-limits to all future mmap(), munmap(), mremap(), and mprotect() calls.
|
| - snapshotMemoryMappings(processFdPub_);
|
| + snapshotMemoryMappings(processFdPub_, proc_self_maps_);
|
| + NOINTR_SYS(sys.close(proc_self_maps_));
|
| + proc_self_maps_ = -1;
|
|
|
| // Creating the trusted thread enables sandboxing
|
| createTrustedThread(processFdPub_, cloneFdPub_, secureMem);
|
|
|