| Index: sandbox/linux/seccomp/sigaction.cc
|
| ===================================================================
|
| --- sandbox/linux/seccomp/sigaction.cc (revision 57969)
|
| +++ sandbox/linux/seccomp/sigaction.cc (working copy)
|
| @@ -1,177 +0,0 @@
|
| -// 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.
|
| -
|
| -// TODO(markus): We currently instrument the restorer functions with calls to
|
| -// the syscallWrapper(). This prevents gdb from properly
|
| -// creating backtraces of code that is running in signal
|
| -// handlers. We might instead want to always override the
|
| -// restorer with a function that contains the "magic" signature
|
| -// but that is not executable. The SEGV handler can detect this
|
| -// and then invoke the appropriate restorer.
|
| -
|
| -#include "debug.h"
|
| -#include "sandbox_impl.h"
|
| -
|
| -namespace playground {
|
| -
|
| -#if defined(__NR_sigaction)
|
| -long Sandbox::sandbox_sigaction(int signum, const void* a_, void* oa_) {
|
| - const SysCalls::kernel_old_sigaction* action =
|
| - reinterpret_cast<const SysCalls::kernel_old_sigaction*>(a_);
|
| - SysCalls::kernel_old_sigaction* old_action =
|
| - reinterpret_cast<SysCalls::kernel_old_sigaction*>(oa_);
|
| -
|
| - long rc = 0;
|
| - long long tm;
|
| - Debug::syscall(&tm, __NR_sigaction, "Executing handler");
|
| - if (signum == SIGSEGV) {
|
| - if (old_action) {
|
| - old_action->sa_handler_ = sa_segv_.sa_handler_;
|
| - old_action->sa_mask = sa_segv_.sa_mask.sig[0];
|
| - old_action->sa_flags = sa_segv_.sa_flags;
|
| - old_action->sa_restorer = sa_segv_.sa_restorer;
|
| - }
|
| - if (action) {
|
| - sa_segv_.sa_handler_ = action->sa_handler_;
|
| - sa_segv_.sa_mask.sig[0] = action->sa_mask;
|
| - sa_segv_.sa_flags = action->sa_flags;
|
| - sa_segv_.sa_restorer = action->sa_restorer;
|
| - }
|
| - } else {
|
| - struct {
|
| - int sysnum;
|
| - long long cookie;
|
| - SigAction sigaction_req;
|
| - } __attribute__((packed)) request;
|
| - request.sysnum = __NR_sigaction;
|
| - request.cookie = cookie();
|
| - request.sigaction_req.sysnum = __NR_sigaction;
|
| - request.sigaction_req.signum = signum;
|
| - request.sigaction_req.action =
|
| - reinterpret_cast<const SysCalls::kernel_sigaction *>(action);
|
| - request.sigaction_req.old_action =
|
| - reinterpret_cast<const SysCalls::kernel_sigaction *>(old_action);
|
| - request.sigaction_req.sigsetsize = 8;
|
| -
|
| - SysCalls sys;
|
| - if (write(sys, processFdPub(), &request, sizeof(request)) !=
|
| - sizeof(request) ||
|
| - read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) {
|
| - die("Failed to forward sigaction() request [sandbox]");
|
| - }
|
| - }
|
| - Debug::elapsed(tm, __NR_sigaction);
|
| - return rc;
|
| -}
|
| -#endif
|
| -
|
| -#if defined(__NR_rt_sigaction)
|
| -#define min(a,b) ({ typeof(a) a_=(a); typeof(b) b_=(b); a_ < b_ ? a_ : b_; })
|
| -#define max(a,b) ({ typeof(a) a_=(a); typeof(b) b_=(b); a_ > b_ ? a_ : b_; })
|
| -
|
| -long Sandbox::sandbox_rt_sigaction(int signum, const void* a_, void* oa_,
|
| - size_t sigsetsize) {
|
| - const SysCalls::kernel_sigaction* action =
|
| - reinterpret_cast<const SysCalls::kernel_sigaction*>(a_);
|
| - SysCalls::kernel_sigaction* old_action =
|
| - reinterpret_cast<SysCalls::kernel_sigaction*>(oa_);
|
| -
|
| - long rc = 0;
|
| - long long tm;
|
| - Debug::syscall(&tm, __NR_rt_sigaction, "Executing handler");
|
| - if (signum == SIGSEGV) {
|
| - size_t theirSize = offsetof(SysCalls::kernel_sigaction, sa_mask) +
|
| - sigsetsize;
|
| - if (old_action) {
|
| - memcpy(old_action, &sa_segv_, min(sizeof(sa_segv_), theirSize));
|
| - memset(old_action + 1, 0, max(0u, theirSize - sizeof(sa_segv_)));
|
| - }
|
| - if (action) {
|
| - memcpy(&sa_segv_, action, min(sizeof(sa_segv_), theirSize));
|
| - memset(&sa_segv_.sa_mask, 0, max(0u, 8 - sigsetsize));
|
| - }
|
| - } else {
|
| - struct {
|
| - int sysnum;
|
| - long long cookie;
|
| - SigAction sigaction_req;
|
| - } __attribute__((packed)) request;
|
| - request.sysnum = __NR_rt_sigaction;
|
| - request.cookie = cookie();
|
| - request.sigaction_req.sysnum = __NR_rt_sigaction;
|
| - request.sigaction_req.signum = signum;
|
| - request.sigaction_req.action = action;
|
| - request.sigaction_req.old_action = old_action;
|
| - request.sigaction_req.sigsetsize = sigsetsize;
|
| -
|
| - SysCalls sys;
|
| - if (write(sys, processFdPub(), &request, sizeof(request)) !=
|
| - sizeof(request) ||
|
| - read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) {
|
| - die("Failed to forward rt_sigaction() request [sandbox]");
|
| - }
|
| - }
|
| - Debug::elapsed(tm, __NR_rt_sigaction);
|
| - return rc;
|
| -}
|
| -#endif
|
| -
|
| -#if defined(__NR_signal)
|
| -void* Sandbox::sandbox_signal(int signum, const void* handler) {
|
| - struct kernel_old_sigaction sa, osa;
|
| - sa.sa_handler_ = reinterpret_cast<void (*)(int)>(handler);
|
| - sa.sa_flags = SA_NODEFER | SA_RESETHAND | SA_RESTORER;
|
| - sa.sa_mask = 0;
|
| - asm volatile(
|
| - "lea 0f, %0\n"
|
| - "jmp 1f\n"
|
| - "0:pop %%eax\n"
|
| - "mov $119, %%eax\n" // __NR_sigreturn
|
| - "int $0x80\n"
|
| - "1:\n"
|
| - : "=r"(sa.sa_restorer));
|
| - long rc = sandbox_sigaction(signum, &sa, &osa);
|
| - if (rc < 0) {
|
| - return (void *)rc;
|
| - }
|
| - return reinterpret_cast<void *>(osa.sa_handler_);
|
| -}
|
| -#endif
|
| -
|
| -bool Sandbox::process_sigaction(int parentMapsFd, int sandboxFd,
|
| - int threadFdPub, int threadFd,
|
| - SecureMem::Args* mem) {
|
| - // We need to intercept sigaction() in order to properly rewrite calls to
|
| - // sigaction(SEGV). While there is no security implication if we didn't do
|
| - // so, it would end up preventing the program from running correctly as the
|
| - // the sandbox's SEGV handler could accidentally get removed. All of this is
|
| - // done in sandbox_{,rt_}sigaction(). But we still bounce through the
|
| - // trusted process as that is the only way we can instrument system calls.
|
| - // This is somewhat needlessly complicated. But as sigaction() is not a
|
| - // performance critical system call, it is easier to do this way than to
|
| - // extend the format of the syscall_table so that it could deal with this
|
| - // special case.
|
| -
|
| - // Read request
|
| - SigAction sigaction_req;
|
| - SysCalls sys;
|
| - if (read(sys, sandboxFd, &sigaction_req, sizeof(sigaction_req)) !=
|
| - sizeof(sigaction_req)) {
|
| - die("Failed to read parameters for sigaction() [process]");
|
| - }
|
| - if (sigaction_req.signum == SIGSEGV) {
|
| - // This should never happen. Something went wrong when intercepting the
|
| - // system call. This is not a security problem, but it clearly doesn't
|
| - // make sense to let the system call pass.
|
| - SecureMem::abandonSystemCall(threadFd, -EINVAL);
|
| - return false;
|
| - }
|
| - SecureMem::sendSystemCall(threadFdPub, false, -1, mem, sigaction_req.sysnum,
|
| - sigaction_req.signum, sigaction_req.action,
|
| - sigaction_req.old_action,
|
| - sigaction_req.sigsetsize);
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
|
|