summaryrefslogtreecommitdiffstats
path: root/sandbox/linux/seccomp/securemem.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/linux/seccomp/securemem.cc')
-rw-r--r--sandbox/linux/seccomp/securemem.cc105
1 files changed, 105 insertions, 0 deletions
diff --git a/sandbox/linux/seccomp/securemem.cc b/sandbox/linux/seccomp/securemem.cc
new file mode 100644
index 0000000..5f07bbe
--- /dev/null
+++ b/sandbox/linux/seccomp/securemem.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "debug.h"
+#include "mutex.h"
+#include "sandbox_impl.h"
+#include "securemem.h"
+
+namespace playground {
+
+void SecureMem::abandonSystemCall(int fd, int err) {
+ void* rc = reinterpret_cast<void *>(err);
+ if (err) {
+ Debug::message("System call failed\n");
+ }
+ Sandbox::SysCalls sys;
+ if (Sandbox::write(sys, fd, &rc, sizeof(rc)) != sizeof(rc)) {
+ Sandbox::die("Failed to send system call");
+ }
+}
+
+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.
+ 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 parentMapsFd, Args* mem) {
+ while (!Mutex::lockMutex(&Sandbox::syscall_mutex_, 500)) {
+ dieIfParentDied(parentMapsFd);
+ }
+ asm volatile(
+ #if defined(__x86_64__)
+ "lock; incq (%0)\n"
+ #elif defined(__i386__)
+ "lock; incl (%0)\n"
+ #else
+ #error Unsupported target platform
+ #endif
+ :
+ : "q"(&mem->sequence)
+ : "memory");
+}
+
+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) {
+ if (!locked) {
+ asm volatile(
+ #if defined(__x86_64__)
+ "lock; incq (%0)\n"
+ #elif defined(__i386__)
+ "lock; incl (%0)\n"
+ #else
+ #error Unsupported target platform
+ #endif
+ :
+ : "q"(&mem->sequence)
+ : "memory");
+ }
+ mem->callType = locked ? -2 : -1;
+ mem->syscallNum = syscallNum;
+ mem->arg1 = arg1;
+ mem->arg2 = arg2;
+ mem->arg3 = arg3;
+ mem->arg4 = arg4;
+ mem->arg5 = arg5;
+ mem->arg6 = arg6;
+ asm volatile(
+ #if defined(__x86_64__)
+ "lock; incq (%0)\n"
+ #elif defined(__i386__)
+ "lock; incl (%0)\n"
+ #else
+ #error Unsupported target platform
+ #endif
+ :
+ : "q"(&mem->sequence)
+ : "memory");
+ Sandbox::SysCalls sys;
+ if (Sandbox::write(sys, fd, &mem->callType, sizeof(int)) != sizeof(int)) {
+ Sandbox::die("Failed to send system call");
+ }
+ if (parentMapsFd >= 0) {
+ while (!Mutex::waitForUnlock(&Sandbox::syscall_mutex_, 500)) {
+ dieIfParentDied(parentMapsFd);
+ }
+ }
+}
+
+} // namespace