diff options
Diffstat (limited to 'sandbox/linux/seccomp/clone.cc')
-rw-r--r-- | sandbox/linux/seccomp/clone.cc | 179 |
1 files changed, 0 insertions, 179 deletions
diff --git a/sandbox/linux/seccomp/clone.cc b/sandbox/linux/seccomp/clone.cc deleted file mode 100644 index 0d35181..0000000 --- a/sandbox/linux/seccomp/clone.cc +++ /dev/null @@ -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 |