| Index: sandbox/linux/seccomp/clone.cc
|
| ===================================================================
|
| --- sandbox/linux/seccomp/clone.cc (revision 57969)
|
| +++ sandbox/linux/seccomp/clone.cc (working copy)
|
| @@ -1,179 +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.
|
| -
|
| -#include "debug.h"
|
| -#include "sandbox_impl.h"
|
| -
|
| -namespace playground {
|
| -
|
| -long Sandbox::sandbox_clone(int flags, char* stack, int* pid, int* ctid,
|
| - void* tls, void *wrapper_sp) {
|
| - long long tm;
|
| - Debug::syscall(&tm, __NR_clone, "Executing handler");
|
| - struct {
|
| - int sysnum;
|
| - long long cookie;
|
| - Clone clone_req;
|
| - } __attribute__((packed)) request;
|
| - request.sysnum = __NR_clone;
|
| - request.cookie = cookie();
|
| - request.clone_req.flags = flags;
|
| - request.clone_req.stack = stack;
|
| - request.clone_req.pid = pid;
|
| - request.clone_req.ctid = ctid;
|
| - request.clone_req.tls = tls;
|
| -
|
| - // TODO(markus): Passing stack == 0 currently does not do the same thing
|
| - // that the kernel would do without the sandbox. This is just going to
|
| - // cause a crash. We should detect this case, and replace the stack pointer
|
| - // with the correct value, instead.
|
| - // This is complicated by the fact that we will temporarily be executing
|
| - // both threads from the same stack. Some synchronization will be necessary.
|
| - // Fortunately, this complication also explains why hardly anybody ever
|
| - // does this.
|
| - // See trusted_thread.cc for more information.
|
| - long rc;
|
| - if (stack == 0) {
|
| - rc = -EINVAL;
|
| - } else {
|
| - // Pass along the address on the stack where syscallWrapper() stored the
|
| - // original CPU registers. These registers will be restored in the newly
|
| - // created thread prior to returning from the wrapped system call.
|
| - #if defined(__x86_64__)
|
| - memcpy(&request.clone_req.regs64, wrapper_sp,
|
| - sizeof(request.clone_req.regs64) + sizeof(void *));
|
| - #elif defined(__i386__)
|
| - memcpy(&request.clone_req.regs32, wrapper_sp,
|
| - sizeof(request.clone_req.regs32) + sizeof(void *));
|
| - #else
|
| - #error Unsupported target platform
|
| - #endif
|
| -
|
| - // In order to unblock the signal mask in the newly created thread and
|
| - // after entering Seccomp mode, we have to call sigreturn(). But that
|
| - // requires access to a proper stack frame describing a valid signal.
|
| - // We trigger a signal now and make sure the stack frame ends up on the
|
| - // new stack. Our segv() handler (in sandbox.cc) does that for us.
|
| - // See trusted_thread.cc for more details on how threads get created.
|
| - //
|
| - // In general we rely on the kernel for generating the signal stack
|
| - // frame, as the exact binary format has been extended several times over
|
| - // the course of the kernel's development. Fortunately, the kernel
|
| - // developers treat the initial part of the stack frame as a stable part
|
| - // of the ABI. So, we can rely on fixed, well-defined offsets for accessing
|
| - // register values and for accessing the signal mask.
|
| - #if defined(__x86_64__)
|
| - // Red zone compensation. The instrumented system call will remove 128
|
| - // bytes from the thread's stack prior to returning to the original
|
| - // call site.
|
| - stack -= 128;
|
| - request.clone_req.stack = stack;
|
| - void *dummy;
|
| - asm volatile("mov %%rsp, %%rcx\n"
|
| - "mov %3, %%rsp\n"
|
| - "int $0\n"
|
| - "mov %%rcx, %%rsp\n"
|
| - : "=a"(request.clone_req.stack), "=&c"(dummy)
|
| - : "a"(__NR_clone + 0xF000), "m"(request.clone_req.stack)
|
| - : "memory");
|
| - #elif defined(__i386__)
|
| - void *dummy;
|
| - asm volatile("mov %%esp, %%ecx\n"
|
| - "mov %3, %%esp\n"
|
| - "int $0\n"
|
| - "mov %%ecx, %%esp\n"
|
| - : "=a"(request.clone_req.stack), "=&c"(dummy)
|
| - : "a"(__NR_clone + 0xF000), "m"(request.clone_req.stack)
|
| - : "memory");
|
| - #else
|
| - #error Unsupported target platform
|
| - #endif
|
| -
|
| - // Adjust the signal stack frame so that it contains the correct stack
|
| - // pointer upon returning from sigreturn().
|
| - #if defined(__x86_64__)
|
| - *(char **)(request.clone_req.stack + 0xA0) = stack;
|
| - #elif defined(__i386__)
|
| - *(char **)(request.clone_req.stack + 0x1C) = stack;
|
| - #else
|
| - #error Unsupported target platform
|
| - #endif
|
| -
|
| - SysCalls sys;
|
| - if (write(sys, processFdPub(), &request, sizeof(request)) !=
|
| - sizeof(request) ||
|
| - read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) {
|
| - die("Failed to forward clone() request [sandbox]");
|
| - }
|
| - }
|
| - Debug::elapsed(tm, __NR_clone);
|
| - return rc;
|
| -}
|
| -
|
| -bool Sandbox::process_clone(int parentMapsFd, int sandboxFd, int threadFdPub,
|
| - int threadFd, SecureMem::Args* mem) {
|
| - // Read request
|
| - Clone clone_req;
|
| - SysCalls sys;
|
| - if (read(sys, sandboxFd, &clone_req, sizeof(clone_req)) !=sizeof(clone_req)){
|
| - die("Failed to read parameters for clone() [process]");
|
| - }
|
| -
|
| - // TODO(markus): add policy restricting parameters for clone
|
| - if ((clone_req.flags & ~CLONE_DETACHED) != (CLONE_VM|CLONE_FS|CLONE_FILES|
|
| - CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|
|
| - CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID)) {
|
| - SecureMem::abandonSystemCall(threadFd, -EPERM);
|
| - return false;
|
| - } else {
|
| - SecureMem::Args* newMem = getNewSecureMem();
|
| - if (!newMem) {
|
| - SecureMem::abandonSystemCall(threadFd, -ENOMEM);
|
| - return false;
|
| - } else {
|
| - // 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(parentMapsFd, mem);
|
| - mem->ret = clone_req.ret;
|
| - #if defined(__x86_64__)
|
| - mem->rbp = clone_req.regs64.rbp;
|
| - mem->rbx = clone_req.regs64.rbx;
|
| - mem->rcx = clone_req.regs64.rcx;
|
| - mem->rdx = clone_req.regs64.rdx;
|
| - mem->rsi = clone_req.regs64.rsi;
|
| - mem->rdi = clone_req.regs64.rdi;
|
| - mem->r8 = clone_req.regs64.r8;
|
| - mem->r9 = clone_req.regs64.r9;
|
| - mem->r10 = clone_req.regs64.r10;
|
| - mem->r11 = clone_req.regs64.r11;
|
| - mem->r12 = clone_req.regs64.r12;
|
| - mem->r13 = clone_req.regs64.r13;
|
| - mem->r14 = clone_req.regs64.r14;
|
| - mem->r15 = clone_req.regs64.r15;
|
| - #elif defined(__i386__)
|
| - mem->ebp = clone_req.regs32.ebp;
|
| - mem->edi = clone_req.regs32.edi;
|
| - mem->esi = clone_req.regs32.esi;
|
| - mem->edx = clone_req.regs32.edx;
|
| - mem->ecx = clone_req.regs32.ecx;
|
| - mem->ebx = clone_req.regs32.ebx;
|
| - #else
|
| - #error Unsupported target platform
|
| - #endif
|
| - newMem->sequence = 0;
|
| - newMem->shmId = -1;
|
| - mem->newSecureMem = newMem;
|
| - mem->processFdPub = processFdPub_;
|
| - mem->cloneFdPub = cloneFdPub_;
|
| -
|
| - 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;
|
| - }
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
|
|