summaryrefslogtreecommitdiffstats
path: root/sandbox/linux/seccomp/sigprocmask.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/linux/seccomp/sigprocmask.cc')
-rw-r--r--sandbox/linux/seccomp/sigprocmask.cc120
1 files changed, 120 insertions, 0 deletions
diff --git a/sandbox/linux/seccomp/sigprocmask.cc b/sandbox/linux/seccomp/sigprocmask.cc
new file mode 100644
index 0000000..9ff2922
--- /dev/null
+++ b/sandbox/linux/seccomp/sigprocmask.cc
@@ -0,0 +1,120 @@
+// 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 "sandbox_impl.h"
+
+namespace playground {
+
+// If the sandboxed process tries to mask SIGSEGV, there is a good chance
+// the process will eventually get terminated. If this is really ever a
+// problem, we can hide the fact that SIGSEGV is unmasked. But I don't think
+// we really need this. Masking of synchronous signals is rarely necessary.
+
+#if defined(__NR_sigprocmask)
+long Sandbox::sandbox_sigprocmask(int how, const void* set, void* old_set) {
+ long long tm;
+ Debug::syscall(&tm, __NR_sigprocmask, "Executing handler");
+
+ // Access the signal mask by triggering a SEGV and modifying the signal state
+ // prior to calling rt_sigreturn().
+ long res = -ENOSYS;
+ #if defined(__x86_64__)
+ #error x86-64 does not support sigprocmask(); use rt_sigprocmask() instead
+ #elif defined(__i386__)
+ asm volatile(
+ "push %%ebx\n"
+ "movl %2, %%ebx\n"
+ "int $0\n"
+ "pop %%ebx\n"
+ : "=a"(res)
+ : "0"(__NR_sigprocmask), "ri"((long)how),
+ "c"((long)set), "d"((long)old_set)
+ : "esp", "memory");
+ #else
+ #error Unsupported target platform
+ #endif
+
+ // Update our shadow signal mask, so that we can copy it upon creation of
+ // new threads.
+ if (res == 0 && set != NULL) {
+ SecureMem::Args* args = getSecureMem();
+ switch (how) {
+ case SIG_BLOCK:
+ *(unsigned long long *)&args->signalMask |= *(unsigned long long *)set;
+ break;
+ case SIG_UNBLOCK:
+ *(unsigned long long *)&args->signalMask &= ~*(unsigned long long *)set;
+ break;
+ case SIG_SETMASK:
+ *(unsigned long long *)&args->signalMask = *(unsigned long long *)set;
+ break;
+ default:
+ break;
+ }
+ }
+
+ Debug::elapsed(tm, __NR_sigprocmask);
+
+ return res;
+}
+#endif
+
+#if defined(__NR_rt_sigprocmask)
+long Sandbox::sandbox_rt_sigprocmask(int how, const void* set, void* old_set,
+ size_t bytes) {
+ long long tm;
+ Debug::syscall(&tm, __NR_rt_sigprocmask, "Executing handler");
+
+ // Access the signal mask by triggering a SEGV and modifying the signal state
+ // prior to calling rt_sigreturn().
+ long res = -ENOSYS;
+ #if defined(__x86_64__)
+ asm volatile(
+ "movq %5, %%r10\n"
+ "int $0\n"
+ : "=a"(res)
+ : "0"(__NR_rt_sigprocmask), "D"((long)how),
+ "S"((long)set), "d"((long)old_set), "r"((long)bytes)
+ : "r10", "r11", "rcx", "memory");
+ #elif defined(__i386__)
+ asm volatile(
+ "push %%ebx\n"
+ "movl %2, %%ebx\n"
+ "int $0\n"
+ "pop %%ebx\n"
+ : "=a"(res)
+ : "0"(__NR_rt_sigprocmask), "ri"((long)how),
+ "c"((long)set), "d"((long)old_set), "S"((long)bytes)
+ : "esp", "memory");
+ #else
+ #error Unsupported target platform
+ #endif
+
+ // Update our shadow signal mask, so that we can copy it upon creation of
+ // new threads.
+ if (res == 0 && set != NULL && bytes >= 8) {
+ SecureMem::Args* args = getSecureMem();
+ switch (how) {
+ case SIG_BLOCK:
+ *(unsigned long long *)&args->signalMask |= *(unsigned long long *)set;
+ break;
+ case SIG_UNBLOCK:
+ *(unsigned long long *)&args->signalMask &= ~*(unsigned long long *)set;
+ break;
+ case SIG_SETMASK:
+ *(unsigned long long *)&args->signalMask = *(unsigned long long *)set;
+ break;
+ default:
+ break;
+ }
+ }
+
+ Debug::elapsed(tm, __NR_rt_sigprocmask);
+
+ return res;
+}
+#endif
+
+} // namespace