Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1072)

Side by Side Diff: sandbox/linux/seccomp/clone.cc

Issue 3225010: Pull seccomp-sandbox in via DEPS rather than using an in-tree copy... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sandbox/linux/seccomp/allocator.cc ('k') | sandbox/linux/seccomp/debug.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "debug.h"
6 #include "sandbox_impl.h"
7
8 namespace playground {
9
10 long Sandbox::sandbox_clone(int flags, char* stack, int* pid, int* ctid,
11 void* tls, void *wrapper_sp) {
12 long long tm;
13 Debug::syscall(&tm, __NR_clone, "Executing handler");
14 struct {
15 int sysnum;
16 long long cookie;
17 Clone clone_req;
18 } __attribute__((packed)) request;
19 request.sysnum = __NR_clone;
20 request.cookie = cookie();
21 request.clone_req.flags = flags;
22 request.clone_req.stack = stack;
23 request.clone_req.pid = pid;
24 request.clone_req.ctid = ctid;
25 request.clone_req.tls = tls;
26
27 // TODO(markus): Passing stack == 0 currently does not do the same thing
28 // that the kernel would do without the sandbox. This is just going to
29 // cause a crash. We should detect this case, and replace the stack pointer
30 // with the correct value, instead.
31 // This is complicated by the fact that we will temporarily be executing
32 // both threads from the same stack. Some synchronization will be necessary.
33 // Fortunately, this complication also explains why hardly anybody ever
34 // does this.
35 // See trusted_thread.cc for more information.
36 long rc;
37 if (stack == 0) {
38 rc = -EINVAL;
39 } else {
40 // Pass along the address on the stack where syscallWrapper() stored the
41 // original CPU registers. These registers will be restored in the newly
42 // created thread prior to returning from the wrapped system call.
43 #if defined(__x86_64__)
44 memcpy(&request.clone_req.regs64, wrapper_sp,
45 sizeof(request.clone_req.regs64) + sizeof(void *));
46 #elif defined(__i386__)
47 memcpy(&request.clone_req.regs32, wrapper_sp,
48 sizeof(request.clone_req.regs32) + sizeof(void *));
49 #else
50 #error Unsupported target platform
51 #endif
52
53 // In order to unblock the signal mask in the newly created thread and
54 // after entering Seccomp mode, we have to call sigreturn(). But that
55 // requires access to a proper stack frame describing a valid signal.
56 // We trigger a signal now and make sure the stack frame ends up on the
57 // new stack. Our segv() handler (in sandbox.cc) does that for us.
58 // See trusted_thread.cc for more details on how threads get created.
59 //
60 // In general we rely on the kernel for generating the signal stack
61 // frame, as the exact binary format has been extended several times over
62 // the course of the kernel's development. Fortunately, the kernel
63 // developers treat the initial part of the stack frame as a stable part
64 // of the ABI. So, we can rely on fixed, well-defined offsets for accessing
65 // register values and for accessing the signal mask.
66 #if defined(__x86_64__)
67 // Red zone compensation. The instrumented system call will remove 128
68 // bytes from the thread's stack prior to returning to the original
69 // call site.
70 stack -= 128;
71 request.clone_req.stack = stack;
72 void *dummy;
73 asm volatile("mov %%rsp, %%rcx\n"
74 "mov %3, %%rsp\n"
75 "int $0\n"
76 "mov %%rcx, %%rsp\n"
77 : "=a"(request.clone_req.stack), "=&c"(dummy)
78 : "a"(__NR_clone + 0xF000), "m"(request.clone_req.stack)
79 : "memory");
80 #elif defined(__i386__)
81 void *dummy;
82 asm volatile("mov %%esp, %%ecx\n"
83 "mov %3, %%esp\n"
84 "int $0\n"
85 "mov %%ecx, %%esp\n"
86 : "=a"(request.clone_req.stack), "=&c"(dummy)
87 : "a"(__NR_clone + 0xF000), "m"(request.clone_req.stack)
88 : "memory");
89 #else
90 #error Unsupported target platform
91 #endif
92
93 // Adjust the signal stack frame so that it contains the correct stack
94 // pointer upon returning from sigreturn().
95 #if defined(__x86_64__)
96 *(char **)(request.clone_req.stack + 0xA0) = stack;
97 #elif defined(__i386__)
98 *(char **)(request.clone_req.stack + 0x1C) = stack;
99 #else
100 #error Unsupported target platform
101 #endif
102
103 SysCalls sys;
104 if (write(sys, processFdPub(), &request, sizeof(request)) !=
105 sizeof(request) ||
106 read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) {
107 die("Failed to forward clone() request [sandbox]");
108 }
109 }
110 Debug::elapsed(tm, __NR_clone);
111 return rc;
112 }
113
114 bool Sandbox::process_clone(int parentMapsFd, int sandboxFd, int threadFdPub,
115 int threadFd, SecureMem::Args* mem) {
116 // Read request
117 Clone clone_req;
118 SysCalls sys;
119 if (read(sys, sandboxFd, &clone_req, sizeof(clone_req)) !=sizeof(clone_req)){
120 die("Failed to read parameters for clone() [process]");
121 }
122
123 // TODO(markus): add policy restricting parameters for clone
124 if ((clone_req.flags & ~CLONE_DETACHED) != (CLONE_VM|CLONE_FS|CLONE_FILES|
125 CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|
126 CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID)) {
127 SecureMem::abandonSystemCall(threadFd, -EPERM);
128 return false;
129 } else {
130 SecureMem::Args* newMem = getNewSecureMem();
131 if (!newMem) {
132 SecureMem::abandonSystemCall(threadFd, -ENOMEM);
133 return false;
134 } else {
135 // clone() has unusual semantics. We don't want to return back into the
136 // trusted thread, but instead we need to continue execution at the IP
137 // where we got called initially.
138 SecureMem::lockSystemCall(parentMapsFd, mem);
139 mem->ret = clone_req.ret;
140 #if defined(__x86_64__)
141 mem->rbp = clone_req.regs64.rbp;
142 mem->rbx = clone_req.regs64.rbx;
143 mem->rcx = clone_req.regs64.rcx;
144 mem->rdx = clone_req.regs64.rdx;
145 mem->rsi = clone_req.regs64.rsi;
146 mem->rdi = clone_req.regs64.rdi;
147 mem->r8 = clone_req.regs64.r8;
148 mem->r9 = clone_req.regs64.r9;
149 mem->r10 = clone_req.regs64.r10;
150 mem->r11 = clone_req.regs64.r11;
151 mem->r12 = clone_req.regs64.r12;
152 mem->r13 = clone_req.regs64.r13;
153 mem->r14 = clone_req.regs64.r14;
154 mem->r15 = clone_req.regs64.r15;
155 #elif defined(__i386__)
156 mem->ebp = clone_req.regs32.ebp;
157 mem->edi = clone_req.regs32.edi;
158 mem->esi = clone_req.regs32.esi;
159 mem->edx = clone_req.regs32.edx;
160 mem->ecx = clone_req.regs32.ecx;
161 mem->ebx = clone_req.regs32.ebx;
162 #else
163 #error Unsupported target platform
164 #endif
165 newMem->sequence = 0;
166 newMem->shmId = -1;
167 mem->newSecureMem = newMem;
168 mem->processFdPub = processFdPub_;
169 mem->cloneFdPub = cloneFdPub_;
170
171 SecureMem::sendSystemCall(threadFdPub, true, parentMapsFd, mem,
172 __NR_clone, clone_req.flags, clone_req.stack,
173 clone_req.pid, clone_req.ctid, clone_req.tls);
174 return true;
175 }
176 }
177 }
178
179 } // namespace
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp/allocator.cc ('k') | sandbox/linux/seccomp/debug.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698