summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authormarkus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-07 06:09:38 +0000
committermarkus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-07 06:09:38 +0000
commita9c54a176540e3a8173d72a1794cac3855bc9ce0 (patch)
tree7d316f2558c7e4f923d0c97ef45c4ed08b59cb45 /sandbox
parent282f4d24b40587c701ede40b014035ceffc9a3ea (diff)
downloadchromium_src-a9c54a176540e3a8173d72a1794cac3855bc9ce0.zip
chromium_src-a9c54a176540e3a8173d72a1794cac3855bc9ce0.tar.gz
chromium_src-a9c54a176540e3a8173d72a1794cac3855bc9ce0.tar.bz2
Allow the seccomp sandbox to be enabled, even if the suid sandbox has
already put a chroot() jail around it. The only tricky part is access to /proc/self/maps, but we can safely pass in an open file descriptor. BUG=26527 Review URL: http://codereview.chromium.org/371047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31372 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/linux/seccomp/access.cc6
-rw-r--r--sandbox/linux/seccomp/clone.cc8
-rw-r--r--sandbox/linux/seccomp/exit.cc7
-rw-r--r--sandbox/linux/seccomp/ioctl.cc2
-rw-r--r--sandbox/linux/seccomp/ipc.cc10
-rw-r--r--sandbox/linux/seccomp/madvise.cc2
-rw-r--r--sandbox/linux/seccomp/maps.cc19
-rw-r--r--sandbox/linux/seccomp/maps.h12
-rw-r--r--sandbox/linux/seccomp/mmap.cc2
-rw-r--r--sandbox/linux/seccomp/mprotect.cc5
-rw-r--r--sandbox/linux/seccomp/munmap.cc2
-rw-r--r--sandbox/linux/seccomp/open.cc6
-rw-r--r--sandbox/linux/seccomp/sandbox.cc43
-rw-r--r--sandbox/linux/seccomp/sandbox.h3
-rw-r--r--sandbox/linux/seccomp/sandbox_impl.h25
-rw-r--r--sandbox/linux/seccomp/securemem.cc26
-rw-r--r--sandbox/linux/seccomp/socketcall.cc29
-rw-r--r--sandbox/linux/seccomp/stat.cc6
-rw-r--r--sandbox/linux/seccomp/syscall_table.h2
-rw-r--r--sandbox/linux/seccomp/trusted_process.cc29
20 files changed, 141 insertions, 103 deletions
diff --git a/sandbox/linux/seccomp/access.cc b/sandbox/linux/seccomp/access.cc
index 0a0d0e5..9e79d12 100644
--- a/sandbox/linux/seccomp/access.cc
+++ b/sandbox/linux/seccomp/access.cc
@@ -29,7 +29,7 @@ int Sandbox::sandbox_access(const char *pathname, int mode) {
return static_cast<int>(rc);
}
-bool Sandbox::process_access(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_access(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
SysCalls sys;
@@ -56,7 +56,7 @@ bool Sandbox::process_access(int parentProc, int sandboxFd, int threadFdPub,
}
return false;
}
- SecureMem::lockSystemCall(parentProc, mem);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
if (read(sys, sandboxFd, mem->pathname, access_req.path_length) !=
(ssize_t)access_req.path_length) {
goto read_parm_failed;
@@ -68,7 +68,7 @@ bool Sandbox::process_access(int parentProc, int sandboxFd, int threadFdPub,
"\"").c_str());
// Tell trusted thread to access the file.
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem, __NR_access,
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem, __NR_access,
mem->pathname - (char*)mem + (char*)mem->self,
access_req.mode);
return true;
diff --git a/sandbox/linux/seccomp/clone.cc b/sandbox/linux/seccomp/clone.cc
index 109e5c6..2b6703f 100644
--- a/sandbox/linux/seccomp/clone.cc
+++ b/sandbox/linux/seccomp/clone.cc
@@ -42,7 +42,7 @@ int Sandbox::sandbox_clone(int flags, void* stack, int* pid, int* ctid,
return static_cast<int>(rc);
}
-bool Sandbox::process_clone(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_clone(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
Clone clone_req;
@@ -66,7 +66,7 @@ bool Sandbox::process_clone(int parentProc, int sandboxFd, int threadFdPub,
// clone() has unusual semantics. We don't want to return back into the
// trusted thread, but instead we need to continue execution at the IP
// where we got called initially.
- SecureMem::lockSystemCall(parentProc, mem);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
mem->ret = clone_req.ret;
#if defined(__x86_64__)
mem->rbp = clone_req.regs64.rbp;
@@ -100,8 +100,8 @@ bool Sandbox::process_clone(int parentProc, int sandboxFd, int threadFdPub,
mem->processFdPub = processFdPub_;
mem->cloneFdPub = cloneFdPub_;
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem, __NR_clone,
- clone_req.flags, clone_req.stack,
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem,
+ __NR_clone, clone_req.flags, clone_req.stack,
clone_req.pid, clone_req.ctid, clone_req.tls);
return true;
}
diff --git a/sandbox/linux/seccomp/exit.cc b/sandbox/linux/seccomp/exit.cc
index 23ebc55..4cf274a 100644
--- a/sandbox/linux/seccomp/exit.cc
+++ b/sandbox/linux/seccomp/exit.cc
@@ -22,10 +22,11 @@ int Sandbox::sandbox_exit(int status) {
}
}
-bool Sandbox::process_exit(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_exit(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
- SecureMem::lockSystemCall(parentProc, mem);
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem, __NR_exit, 0);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem,
+ __NR_exit, 0);
return true;
}
diff --git a/sandbox/linux/seccomp/ioctl.cc b/sandbox/linux/seccomp/ioctl.cc
index ac630a7..46e5a8f 100644
--- a/sandbox/linux/seccomp/ioctl.cc
+++ b/sandbox/linux/seccomp/ioctl.cc
@@ -26,7 +26,7 @@ int Sandbox::sandbox_ioctl(int d, int req, void *arg) {
return static_cast<int>(rc);
}
-bool Sandbox::process_ioctl(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_ioctl(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
IOCtl ioctl_req;
diff --git a/sandbox/linux/seccomp/ipc.cc b/sandbox/linux/seccomp/ipc.cc
index f3ad9a2..91b2ab7 100644
--- a/sandbox/linux/seccomp/ipc.cc
+++ b/sandbox/linux/seccomp/ipc.cc
@@ -108,7 +108,7 @@ int Sandbox::sandbox_shmget(int key, size_t size, int shmflg) {
return static_cast<int>(rc);
}
-bool Sandbox::process_shmat(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_shmat(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
ShmAt shmat_req;
@@ -133,7 +133,7 @@ bool Sandbox::process_shmat(int parentProc, int sandboxFd, int threadFdPub,
return true;
}
-bool Sandbox::process_shmctl(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_shmctl(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
ShmCtl shmctl_req;
@@ -158,7 +158,7 @@ bool Sandbox::process_shmctl(int parentProc, int sandboxFd, int threadFdPub,
return true;
}
-bool Sandbox::process_shmdt(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_shmdt(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
ShmDt shmdt_req;
@@ -193,7 +193,7 @@ bool Sandbox::process_shmdt(int parentProc, int sandboxFd, int threadFdPub,
return true;
}
-bool Sandbox::process_shmget(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_shmget(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
ShmGet shmget_req;
@@ -261,7 +261,7 @@ int Sandbox::sandbox_ipc(unsigned call, int first, int second, int third,
return static_cast<int>(rc);
}
-bool Sandbox::process_ipc(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_ipc(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
IPC ipc_req;
diff --git a/sandbox/linux/seccomp/madvise.cc b/sandbox/linux/seccomp/madvise.cc
index 738da7f..92344df 100644
--- a/sandbox/linux/seccomp/madvise.cc
+++ b/sandbox/linux/seccomp/madvise.cc
@@ -26,7 +26,7 @@ int Sandbox::sandbox_madvise(void* start, size_t length, int advice) {
return static_cast<int>(rc);
}
-bool Sandbox::process_madvise(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_madvise(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
MAdvise madvise_req;
diff --git a/sandbox/linux/seccomp/maps.cc b/sandbox/linux/seccomp/maps.cc
index 0bf9c8a..2c64b7f 100644
--- a/sandbox/linux/seccomp/maps.cc
+++ b/sandbox/linux/seccomp/maps.cc
@@ -15,20 +15,21 @@
namespace playground {
-Maps::Maps(const std::string& maps_file) :
- maps_file_(maps_file),
+Maps::Maps(int proc_self_maps) :
+ proc_self_maps_(proc_self_maps),
begin_iter_(this, true, false),
end_iter_(this, false, true),
vsyscall_(0) {
- int fd = open(maps_file.c_str(), O_RDONLY);
Sandbox::SysCalls sys;
- if (fd >= 0) {
+ if (proc_self_maps_ >= 0 &&
+ !sys.lseek(proc_self_maps_, 0, SEEK_SET)) {
char buf[256] = { 0 };
int len = 0, rc = 1;
bool long_line = false;
do {
if (rc > 0) {
- rc = Sandbox::read(sys, fd, buf + len, sizeof(buf) - len - 1);
+ rc = Sandbox::read(sys, proc_self_maps_, buf + len,
+ sizeof(buf) - len - 1);
if (rc > 0) {
len += rc;
}
@@ -95,7 +96,6 @@ Maps::Maps(const std::string& maps_file) :
}
}
} while (len || long_line);
- NOINTR_SYS(close(fd));
}
}
@@ -155,8 +155,7 @@ char* Maps::allocNearAddr(char* addr, size_t size, int prot) const {
// we will be able to perform relative 32bit jumps from the target address.
size = (size + 4095) & ~4095;
Sandbox::SysCalls sys;
- int fd = sys.open(maps_file_.c_str(), O_RDONLY, 0);
- if (fd < 0) {
+ if (sys.lseek(proc_self_maps_, 0, SEEK_SET)) {
return NULL;
}
@@ -168,7 +167,8 @@ char* Maps::allocNearAddr(char* addr, size_t size, int prot) const {
do {
if (rc > 0) {
do {
- rc = Sandbox::read(sys, fd, buf + len, sizeof(buf) - len - 1);
+ rc = Sandbox::read(sys, proc_self_maps_, buf + len,
+ sizeof(buf) - len - 1);
if (rc > 0) {
len += rc;
}
@@ -213,7 +213,6 @@ char* Maps::allocNearAddr(char* addr, size_t size, int prot) const {
} while (len || long_line);
new_addr = NULL;
done:
- sys.close(fd);
return new_addr;
}
diff --git a/sandbox/linux/seccomp/maps.h b/sandbox/linux/seccomp/maps.h
index 9ecd140..1d30506 100644
--- a/sandbox/linux/seccomp/maps.h
+++ b/sandbox/linux/seccomp/maps.h
@@ -19,7 +19,7 @@ class Library;
class Maps {
friend class Library;
public:
- Maps(const std::string& maps_file);
+ Maps(int proc_self_maps);
~Maps() { }
protected:
@@ -69,12 +69,12 @@ class Maps {
char* vsyscall() const { return vsyscall_; }
protected:
- const std::string maps_file_;
- const Iterator begin_iter_;
- const Iterator end_iter_;
+ const int proc_self_maps_;
+ const Iterator begin_iter_;
+ const Iterator end_iter_;
- LibraryMap libs_;
- char* vsyscall_;
+ LibraryMap libs_;
+ char* vsyscall_;
};
} // namespace
diff --git a/sandbox/linux/seccomp/mmap.cc b/sandbox/linux/seccomp/mmap.cc
index 9ffd110..cefef3a 100644
--- a/sandbox/linux/seccomp/mmap.cc
+++ b/sandbox/linux/seccomp/mmap.cc
@@ -30,7 +30,7 @@ void* Sandbox::sandbox_mmap(void *start, size_t length, int prot, int flags,
return rc;
}
-bool Sandbox::process_mmap(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_mmap(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
SysCalls sys;
diff --git a/sandbox/linux/seccomp/mprotect.cc b/sandbox/linux/seccomp/mprotect.cc
index 1852b7d..11295c7 100644
--- a/sandbox/linux/seccomp/mprotect.cc
+++ b/sandbox/linux/seccomp/mprotect.cc
@@ -26,8 +26,9 @@ int Sandbox::sandbox_mprotect(const void *addr, size_t len, int prot) {
return static_cast<int>(rc);
}
-bool Sandbox::process_mprotect(int parentProc, int sandboxFd, int threadFdPub,
- int threadFd, SecureMem::Args* mem) {
+bool Sandbox::process_mprotect(int parentMapsFd, int sandboxFd,
+ int threadFdPub, int threadFd,
+ SecureMem::Args* mem) {
// Read request
SysCalls sys;
MProtect mprotect_req;
diff --git a/sandbox/linux/seccomp/munmap.cc b/sandbox/linux/seccomp/munmap.cc
index ddab897..d9d74ad 100644
--- a/sandbox/linux/seccomp/munmap.cc
+++ b/sandbox/linux/seccomp/munmap.cc
@@ -25,7 +25,7 @@ int Sandbox::sandbox_munmap(void* start, size_t length) {
return static_cast<int>(rc);
}
-bool Sandbox::process_munmap(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_munmap(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
SysCalls sys;
diff --git a/sandbox/linux/seccomp/open.cc b/sandbox/linux/seccomp/open.cc
index 9b4786b..982d768 100644
--- a/sandbox/linux/seccomp/open.cc
+++ b/sandbox/linux/seccomp/open.cc
@@ -30,7 +30,7 @@ int Sandbox::sandbox_open(const char *pathname, int flags, mode_t mode) {
return static_cast<int>(rc);
}
-bool Sandbox::process_open(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_open(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
SysCalls sys;
@@ -70,7 +70,7 @@ bool Sandbox::process_open(int parentProc, int sandboxFd, int threadFdPub,
return false;
}
- SecureMem::lockSystemCall(parentProc, mem);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
if (read(sys, sandboxFd, mem->pathname, open_req.path_length) !=
(ssize_t)open_req.path_length) {
goto read_parm_failed;
@@ -83,7 +83,7 @@ bool Sandbox::process_open(int parentProc, int sandboxFd, int threadFdPub,
"\"").c_str());
// Tell trusted thread to open the file.
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem, __NR_open,
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem, __NR_open,
mem->pathname - (char*)mem + (char*)mem->self,
open_req.flags, open_req.mode);
return true;
diff --git a/sandbox/linux/seccomp/sandbox.cc b/sandbox/linux/seccomp/sandbox.cc
index 9d80f63..416502b 100644
--- a/sandbox/linux/seccomp/sandbox.cc
+++ b/sandbox/linux/seccomp/sandbox.cc
@@ -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 @@ void (*Sandbox::segv())(int signo) {
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 @@ int Sandbox::supportsSeccompSandbox() {
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 @@ int Sandbox::supportsSeccompSandbox() {
}
}
+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 @@ void Sandbox::startSandbox() {
}
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 @@ void Sandbox::startSandbox() {
// 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 @@ void Sandbox::startSandbox() {
// 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);
diff --git a/sandbox/linux/seccomp/sandbox.h b/sandbox/linux/seccomp/sandbox.h
index 4c5d10a..9873e9d 100644
--- a/sandbox/linux/seccomp/sandbox.h
+++ b/sandbox/linux/seccomp/sandbox.h
@@ -1,7 +1,8 @@
#ifndef SANDBOX_H__
#define SANDBOX_H__
-extern "C" int SupportsSeccompSandbox();
+extern "C" int SupportsSeccompSandbox(int proc_fd);
+extern "C" void SeccompSandboxSetProcSelfMaps(int proc_self_maps);
extern "C" void StartSeccompSandbox();
#endif // SANDBOX_H__
diff --git a/sandbox/linux/seccomp/sandbox_impl.h b/sandbox/linux/seccomp/sandbox_impl.h
index d1cc3ef..2a7366f 100644
--- a/sandbox/linux/seccomp/sandbox_impl.h
+++ b/sandbox/linux/seccomp/sandbox_impl.h
@@ -49,12 +49,23 @@ class Sandbox {
// This could be because the kernel does not support Seccomp mode, or it
// could be because we fail to successfully rewrite all system call entry
// points.
- static int supportsSeccompSandbox() asm("SupportsSeccompSandbox");
+ // "proc_fd" should be a file descriptor for "/proc", or -1 if not provided
+ // by the caller.
+ static int supportsSeccompSandbox(int proc_fd)
+ asm("SupportsSeccompSandbox");
+
+ // The sandbox needs to be able to access "/proc/self/maps". If this file
+ // is not accessible when "startSandbox()" gets called, the caller can
+ // provide an already opened file descriptor by calling "setProcSelfMaps()".
+ // The sandbox becomes the newer owner of this file descriptor and will
+ // eventually close it when "startSandbox()" executes.
+ static void setProcSelfMaps(int proc_self_maps)
+ asm("SeccompSandboxSetProcSelfMaps");
// This is the main public entry point. It finds all system calls that
// need rewriting, sets up the resources needed by the sandbox, and
// enters Seccomp mode.
- static void startSandbox() asm("StartSeccompSandbox");
+ static void startSandbox() asm("StartSeccompSandbox");
private:
// syscall_table.c has to be implemented in C, as C++ does not support
@@ -589,15 +600,16 @@ class Sandbox {
// memory mappings that existed when the sandbox was first enabled. Going
// forward, all these mappings are off-limits for operations such as
// mmap(), munmap(), and mprotect().
- static void initializeProtectedMap(int fd);
+ static int initializeProtectedMap(int fd);
// Helper functions that allows the trusted process to get access to
// "/proc/self/maps" in the sandbox.
- static void snapshotMemoryMappings(int processFd);
+ static void snapshotMemoryMappings(int processFd, int proc_self_maps);
// Main loop for the trusted process.
- static void trustedProcess(int parentProc, int processFdPub, int sandboxFd,
- int cloneFd, SecureMem::Args* secureArena)
+ static void trustedProcess(int parentMapsFd, int processFdPub,
+ int sandboxFd, int cloneFd,
+ SecureMem::Args* secureArena)
__attribute__((noreturn));
// Fork()s of the trusted process.
@@ -609,6 +621,7 @@ class Sandbox {
static void createTrustedThread(int processFdPub, int cloneFdPub,
SecureMem::Args* secureMem);
+ static int proc_self_maps_;
static enum SandboxStatus {
STATUS_UNKNOWN, STATUS_UNSUPPORTED, STATUS_AVAILABLE, STATUS_ENABLED
} status_;
diff --git a/sandbox/linux/seccomp/securemem.cc b/sandbox/linux/seccomp/securemem.cc
index c8e59f9..2cf6903 100644
--- a/sandbox/linux/seccomp/securemem.cc
+++ b/sandbox/linux/seccomp/securemem.cc
@@ -16,23 +16,27 @@ void SecureMem::abandonSystemCall(int fd, int err) {
}
}
-void SecureMem::dieIfParentDied(int parentProc) {
+void SecureMem::dieIfParentDied(int parentMapsFd) {
// The syscall_mutex_ should not be contended. If it is, we are either
// experiencing a very unusual load of system calls that the sandbox is not
// optimized for; or, more likely, the sandboxed process terminated while the
// trusted process was in the middle of waiting for the mutex. We detect
// this situation and terminate the trusted process.
- char proc[80];
- sprintf(proc, "/proc/self/fd/%d/status", parentProc);
- struct stat sb;
- if (stat(proc, &sb)) {
- Sandbox::die();
+ int alive = !lseek(parentMapsFd, 0, SEEK_SET);
+ if (alive) {
+ char buf;
+ do {
+ alive = read(parentMapsFd, &buf, 1);
+ } while (alive < 0 && errno == EINTR);
+ }
+ if (!alive) {
+ Sandbox::die();
}
}
-void SecureMem::lockSystemCall(int parentProc, Args* mem) {
+void SecureMem::lockSystemCall(int parentMapsFd, Args* mem) {
while (!Mutex::lockMutex(&Sandbox::syscall_mutex_, 500)) {
- dieIfParentDied(parentProc);
+ dieIfParentDied(parentMapsFd);
}
asm volatile(
#if defined(__x86_64__)
@@ -47,7 +51,7 @@ void SecureMem::lockSystemCall(int parentProc, Args* mem) {
: "memory");
}
-void SecureMem::sendSystemCallInternal(int fd, bool locked, int parentProc,
+void SecureMem::sendSystemCallInternal(int fd, bool locked, int parentMapsFd,
Args* mem, int syscallNum, void* arg1,
void* arg2, void* arg3, void* arg4,
void* arg5, void* arg6) {
@@ -87,9 +91,9 @@ void SecureMem::sendSystemCallInternal(int fd, bool locked, int parentProc,
if (Sandbox::write(sys, fd, &data, sizeof(data)) != sizeof(data)) {
Sandbox::die("Failed to send system call");
}
- if (parentProc >= 0) {
+ if (parentMapsFd >= 0) {
while (!Mutex::waitForUnlock(&Sandbox::syscall_mutex_, 500)) {
- dieIfParentDied(parentProc);
+ dieIfParentDied(parentMapsFd);
}
}
}
diff --git a/sandbox/linux/seccomp/socketcall.cc b/sandbox/linux/seccomp/socketcall.cc
index d51431d..fe88fa5 100644
--- a/sandbox/linux/seccomp/socketcall.cc
+++ b/sandbox/linux/seccomp/socketcall.cc
@@ -204,8 +204,9 @@ int Sandbox::sandbox_getsockopt(int sockfd, int level, int optname,
return static_cast<int>(rc);
}
-bool Sandbox::process_recvfrom(int parentProc, int sandboxFd, int threadFdPub,
- int threadFd, SecureMem::Args* mem) {
+bool Sandbox::process_recvfrom(int parentMapsFd, int sandboxFd,
+ int threadFdPub, int threadFd,
+ SecureMem::Args* mem) {
// Read request
RecvFrom recvfrom_req;
SysCalls sys;
@@ -231,7 +232,7 @@ bool Sandbox::process_recvfrom(int parentProc, int sandboxFd, int threadFdPub,
return true;
}
-bool Sandbox::process_recvmsg(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_recvmsg(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
RecvMsg recvmsg_req;
@@ -255,7 +256,7 @@ bool Sandbox::process_recvmsg(int parentProc, int sandboxFd, int threadFdPub,
return true;
}
-bool Sandbox::process_sendmsg(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_sendmsg(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
struct {
@@ -307,7 +308,7 @@ bool Sandbox::process_sendmsg(int parentProc, int sandboxFd, int threadFdPub,
// This must be a locked system call, because we have to ensure that the
// untrusted code does not tamper with the msghdr after we have examined it.
- SecureMem::lockSystemCall(parentProc, mem);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
if (sizeof(extra) > 0) {
if (data.msg.msg_namelen > 0) {
data.msg.msg_name = mem->pathname + sizeof(struct msghdr);
@@ -319,14 +320,14 @@ bool Sandbox::process_sendmsg(int parentProc, int sandboxFd, int threadFdPub,
memcpy(mem->pathname + sizeof(struct msghdr), extra, sizeof(extra));
}
memcpy(mem->pathname, &data.msg, sizeof(struct msghdr));
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem,
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem,
__NR_sendmsg, data.sendmsg_req.sockfd,
mem->pathname - (char*)mem + (char*)mem->self,
data.sendmsg_req.flags);
return true;
}
-bool Sandbox::process_sendto(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_sendto(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
SendTo sendto_req;
@@ -359,7 +360,7 @@ bool Sandbox::process_sendto(int parentProc, int sandboxFd, int threadFdPub,
return true;
}
-bool Sandbox::process_setsockopt(int parentProc, int sandboxFd,
+bool Sandbox::process_setsockopt(int parentMapsFd, int sandboxFd,
int threadFdPub, int threadFd,
SecureMem::Args* mem) {
// Read request
@@ -423,7 +424,7 @@ bool Sandbox::process_setsockopt(int parentProc, int sandboxFd,
return false;
}
-bool Sandbox::process_getsockopt(int parentProc, int sandboxFd,
+bool Sandbox::process_getsockopt(int parentMapsFd, int sandboxFd,
int threadFdPub, int threadFd,
SecureMem::Args* mem) {
// Read request
@@ -706,7 +707,7 @@ int Sandbox::sandbox_socketcall(int call, void* args) {
return static_cast<int>(rc);
}
-bool Sandbox::process_socketcall(int parentProc, int sandboxFd,
+bool Sandbox::process_socketcall(int parentMapsFd, int sandboxFd,
int threadFdPub, int threadFd,
SecureMem::Args* mem) {
// Read request
@@ -824,9 +825,9 @@ bool Sandbox::process_socketcall(int parentProc, int sandboxFd,
// that should not be tampered with after it has been inspected. Copy it
// into the write-protected securely shared memory before telling the
// trusted thread to execute the socket call.
- SecureMem::lockSystemCall(parentProc, mem);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
memcpy(mem->pathname, &socketcall_req.args, sizeof(socketcall_req.args));
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem,
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem,
__NR_socketcall, socketcall_req.call,
mem->pathname - (char*)mem + (char*)mem->self);
return true;
@@ -970,7 +971,7 @@ bool Sandbox::process_socketcall(int parentProc, int sandboxFd,
// This must be a locked system call, because we have to ensure that
// the untrusted code does not tamper with the msghdr after we have
// examined it.
- SecureMem::lockSystemCall(parentProc, mem);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
socketcall_req.args.sendmsg.msg =
reinterpret_cast<struct msghdr*>(mem->pathname +
sizeof(socketcall_req.args) -
@@ -989,7 +990,7 @@ bool Sandbox::process_socketcall(int parentProc, int sandboxFd,
sendmsgExtra, numSendmsgExtra);
}
memcpy(mem->pathname + sizeof(socketcall_req.args), msg, sizeof(*msg));
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem,
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem,
__NR_socketcall, socketcall_req.call,
mem->pathname - (char*)mem + (char*)mem->self);
return true;
diff --git a/sandbox/linux/seccomp/stat.cc b/sandbox/linux/seccomp/stat.cc
index 8634fdf..7f958c6 100644
--- a/sandbox/linux/seccomp/stat.cc
+++ b/sandbox/linux/seccomp/stat.cc
@@ -59,7 +59,7 @@ int Sandbox::sandbox_stat64(const char *path, void *buf) {
}
#endif
-bool Sandbox::process_stat(int parentProc, int sandboxFd, int threadFdPub,
+bool Sandbox::process_stat(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMem::Args* mem) {
// Read request
SysCalls sys;
@@ -85,7 +85,7 @@ bool Sandbox::process_stat(int parentProc, int sandboxFd, int threadFdPub,
}
return false;
}
- SecureMem::lockSystemCall(parentProc, mem);
+ SecureMem::lockSystemCall(parentMapsFd, mem);
if (read(sys, sandboxFd, mem->pathname, stat_req.path_length) !=
(ssize_t)stat_req.path_length) {
goto read_parm_failed;
@@ -97,7 +97,7 @@ bool Sandbox::process_stat(int parentProc, int sandboxFd, int threadFdPub,
"\"").c_str());
// Tell trusted thread to stat the file.
- SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem,
+ SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem,
#if defined(__i386__)
stat_req.sysnum == __NR_stat64 ? __NR_stat64 :
#endif
diff --git a/sandbox/linux/seccomp/syscall_table.h b/sandbox/linux/seccomp/syscall_table.h
index 49c2880..fffcdb7 100644
--- a/sandbox/linux/seccomp/syscall_table.h
+++ b/sandbox/linux/seccomp/syscall_table.h
@@ -16,7 +16,7 @@ namespace playground {
struct SyscallTable {
void *handler;
- bool (*trustedProcess)(int parentProc, int sandboxFd, int threadFdPub,
+ bool (*trustedProcess)(int parentMapsFd, int sandboxFd, int threadFdPub,
int threadFd, SecureMemArgs* mem);
};
extern const struct SyscallTable syscallTable[]
diff --git a/sandbox/linux/seccomp/trusted_process.cc b/sandbox/linux/seccomp/trusted_process.cc
index b4bee94..3686277 100644
--- a/sandbox/linux/seccomp/trusted_process.cc
+++ b/sandbox/linux/seccomp/trusted_process.cc
@@ -21,7 +21,7 @@ SecureMem::Args* Sandbox::getSecureMem() {
return NULL;
}
-void Sandbox::trustedProcess(int parentProc, int processFdPub, int sandboxFd,
+void Sandbox::trustedProcess(int parentMapsFd, int processFdPub, int sandboxFd,
int cloneFd, SecureMem::Args* secureArena) {
std::map<long long, struct Thread> threads;
SysCalls sys;
@@ -99,7 +99,7 @@ newThreadCreated:
// Dispatch system call to handler function. Treat both exit() and clone()
// specially.
- if (syscallTable[header.sysnum].trustedProcess(parentProc,
+ if (syscallTable[header.sysnum].trustedProcess(parentMapsFd,
sandboxFd,
currentThread->fdPub,
currentThread->fd,
@@ -117,7 +117,7 @@ newThreadCreated:
}
}
-void Sandbox::initializeProtectedMap(int fd) {
+int Sandbox::initializeProtectedMap(int fd) {
int mapsFd;
if (!getFd(fd, &mapsFd, NULL, NULL, NULL)) {
maps_failure:
@@ -152,8 +152,6 @@ void Sandbox::initializeProtectedMap(int fd) {
}
truncated = strchr(line, '\n') == NULL;
}
- SysCalls sys;
- NOINTR_SYS(sys.close(mapsFd));
// Prevent low address memory allocations. Some buggy kernels allow those
if (protectedMap_[0] < (64 << 10)) {
@@ -161,9 +159,12 @@ void Sandbox::initializeProtectedMap(int fd) {
}
// Let the sandbox know that we are done parsing the memory map.
+ SysCalls sys;
if (write(sys, fd, &mapsFd, sizeof(mapsFd)) != sizeof(mapsFd)) {
goto maps_failure;
}
+
+ return mapsFd;
}
SecureMem::Args* Sandbox::createTrustedProcess(int processFdPub, int sandboxFd,
@@ -189,13 +190,6 @@ SecureMem::Args* Sandbox::createTrustedProcess(int processFdPub, int sandboxFd,
syscall_mutex_ = 0x80000000;
- // Hold on to a file handle in the parent's process directory. We can use
- // this later to reliably tell if the parent died.
- int parentProc = open("/proc/self/", O_RDONLY|O_DIRECTORY);
- if (parentProc < 0) {
- die("Failed to access /proc/self");
- }
-
// Create a trusted process that can evaluate system call parameters and
// decide whether a system call should execute. This process runs outside of
// the seccomp sandbox. It communicates with the sandbox'd process through
@@ -211,7 +205,7 @@ SecureMem::Args* Sandbox::createTrustedProcess(int processFdPub, int sandboxFd,
// If we don't know the list of our open file handles, just try closing
// all valid ones.
for (int fd = sysconf(_SC_OPEN_MAX); --fd > 2; ) {
- if (fd != parentProc && fd != sandboxFd && fd != cloneFd) {
+ if (fd != sandboxFd && fd != cloneFd) {
close(fd);
}
}
@@ -224,8 +218,7 @@ SecureMem::Args* Sandbox::createTrustedProcess(int processFdPub, int sandboxFd,
continue;
int fd = atoi(res->d_name);
if (fd > 2 &&
- fd != parentProc && fd != sandboxFd && fd != cloneFd &&
- fd != dirfd(dir)) {
+ fd != sandboxFd && fd != cloneFd && fd != dirfd(dir)) {
close(fd);
}
}
@@ -241,15 +234,15 @@ SecureMem::Args* Sandbox::createTrustedProcess(int processFdPub, int sandboxFd,
#endif
}
- initializeProtectedMap(sandboxFd);
- trustedProcess(parentProc, processFdPub, sandboxFd, cloneFd, secureArena);
+ int parentMapsFd = initializeProtectedMap(sandboxFd);
+ trustedProcess(parentMapsFd, processFdPub, sandboxFd,
+ cloneFd, secureArena);
die();
}
// We are still in the untrusted code. Deny access to restricted resources.
mprotect(secureArena, 8192*kMaxThreads, PROT_NONE);
mprotect(&syscall_mutex_, 4096, PROT_NONE);
- close(parentProc);
close(sandboxFd);
return secureArena;