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

Side by Side Diff: sandbox/linux/seccomp-bpf/sandbox_bpf.cc

Issue 10535089: Avoid all library calls (including calls to destructors) after enabling the sandbox. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 6 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-bpf/sandbox_bpf.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
6 #include "sandbox/linux/seccomp-bpf/verifier.h" 6 #include "sandbox/linux/seccomp-bpf/verifier.h"
7 7
8 // The kernel gives us a sandbox, we turn it into a playground :-) 8 // The kernel gives us a sandbox, we turn it into a playground :-)
9 // This is version 2 of the playground; version 1 was built on top of 9 // This is version 2 of the playground; version 1 was built on top of
10 // pre-BPF seccomp mode. 10 // pre-BPF seccomp mode.
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 sigprocmask(SIG_UNBLOCK, &mask, NULL)) { 205 sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
206 goto filter_failed; 206 goto filter_failed;
207 } 207 }
208 208
209 // We can't handle stacked evaluators, yet. We'll get there eventually 209 // We can't handle stacked evaluators, yet. We'll get there eventually
210 // though. Hang tight. 210 // though. Hang tight.
211 if (evaluators_.size() != 1) { 211 if (evaluators_.size() != 1) {
212 die("Not implemented"); 212 die("Not implemented");
213 } 213 }
214 214
215 // Assemble the BPF filter program.
216 Program *program = new Program();
jln (very slow on Chromium) 2012/06/12 19:16:23 I would love if we didn't have to keep track (and
Markus (顧孟勤) 2012/06/12 19:35:05 This is tricky, and I don't think I can do it with
jln (very slow on Chromium) 2012/06/12 20:22:51 You're right, this becomes even more confusing.
217 if (!program) {
218 die("Out of memory");
219 }
220
215 // If the architecture doesn't match SECCOMP_ARCH, disallow the 221 // If the architecture doesn't match SECCOMP_ARCH, disallow the
216 // system call. 222 // system call.
217 std::vector<struct sock_filter> program; 223 program->push_back((struct sock_filter)
218 program.push_back((struct sock_filter)
219 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch))); 224 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch)));
220 program.push_back((struct sock_filter) 225 program->push_back((struct sock_filter)
221 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0)); 226 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0));
222 227
223 // TODO: Instead of killing outright, we should raise a SIGSYS and 228 // TODO: Instead of killing outright, we should raise a SIGSYS and
224 // report a useful error message. SIGKILL cannot be trapped by the 229 // report a useful error message. SIGKILL cannot be trapped by the
225 // debugger and essentially makes the program fail in a way that is 230 // debugger and essentially makes the program fail in a way that is
226 // almost impossible to debug. 231 // almost impossible to debug.
227 program.push_back((struct sock_filter) 232 program->push_back((struct sock_filter)
228 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)); 233 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL));
229 234
230 // Grab the system call number, so that we can implement jump tables. 235 // Grab the system call number, so that we can implement jump tables.
231 program.push_back((struct sock_filter) 236 program->push_back((struct sock_filter)
232 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr))); 237 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr)));
233 238
234 // On Intel architectures, verify that system call numbers are in the 239 // On Intel architectures, verify that system call numbers are in the
235 // expected number range. The older i386 and x86-64 APIs clear bit 30 240 // expected number range. The older i386 and x86-64 APIs clear bit 30
236 // on all system calls. The newer x86-32 API always sets bit 30. 241 // on all system calls. The newer x86-32 API always sets bit 30.
237 #if defined(__i386__) || defined(__x86_64__) 242 #if defined(__i386__) || defined(__x86_64__)
238 #if defined(__x86_64__) && defined(__ILP32__) 243 #if defined(__x86_64__) && defined(__ILP32__)
239 program.push_back((struct sock_filter) 244 program->push_back((struct sock_filter)
240 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0)); 245 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0));
241 #else 246 #else
242 program.push_back((struct sock_filter) 247 program->push_back((struct sock_filter)
243 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1)); 248 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1));
244 #endif 249 #endif
245 // TODO: raise a suitable SIGSYS signal 250 // TODO: raise a suitable SIGSYS signal
246 program.push_back((struct sock_filter) 251 program->push_back((struct sock_filter)
247 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)); 252 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL));
248 #endif 253 #endif
249 254
250 // Evaluate all possible system calls and depending on their 255 // Evaluate all possible system calls and depending on their
251 // exit codes generate a BPF filter. 256 // exit codes generate a BPF filter.
252 // This is very inefficient right now. We need to be much smarter 257 // This is very inefficient right now. We need to be much smarter
253 // eventually. 258 // eventually.
254 // We currently incur a O(N) overhead on each system call, with N 259 // We currently incur a O(N) overhead on each system call, with N
255 // being the number of system calls. It is easy to get this down to 260 // being the number of system calls. It is easy to get this down to
256 // O(log_2(M)) with M being the number of system calls that need special 261 // O(log_2(M)) with M being the number of system calls that need special
(...skipping 21 matching lines...) Expand all
278 die("Invalid ErrorCode reported by sandbox system call evaluator"); 283 die("Invalid ErrorCode reported by sandbox system call evaluator");
279 } 284 }
280 break; 285 break;
281 } 286 }
282 if (sysnum <= MAX_SYSCALL) { 287 if (sysnum <= MAX_SYSCALL) {
283 // We compute the default behavior (e.g. fail open or fail closed) by 288 // We compute the default behavior (e.g. fail open or fail closed) by
284 // calling the system call evaluator with a system call bigger than 289 // calling the system call evaluator with a system call bigger than
285 // MAX_SYSCALL. 290 // MAX_SYSCALL.
286 // In other words, the very last iteration in our loop becomes the 291 // In other words, the very last iteration in our loop becomes the
287 // fallback case and we don't need to do any comparisons. 292 // fallback case and we don't need to do any comparisons.
288 program.push_back((struct sock_filter) 293 program->push_back((struct sock_filter)
289 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1)); 294 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1));
290 } 295 }
291 program.push_back((struct sock_filter) 296 program->push_back((struct sock_filter)
292 BPF_STMT(BPF_RET+BPF_K, ret)); 297 BPF_STMT(BPF_RET+BPF_K, ret));
293 } 298 }
294 299
295 // Make sure compilation resulted in BPF program that executes 300 // Make sure compilation resulted in BPF program that executes
296 // correctly. Otherwise, there is an internal error in our BPF compiler. 301 // correctly. Otherwise, there is an internal error in our BPF compiler.
297 // There is really nothing the caller can do until the bug is fixed. 302 // There is really nothing the caller can do until the bug is fixed.
298 const char *err; 303 const char *err;
299 if (!Verifier::verifyBPF(program, evaluators_, &err)) { 304 if (!Verifier::verifyBPF(*program, evaluators_, &err)) {
300 die(err); 305 die(err);
301 } 306 }
302 307
308 // We want to be very careful in not imposing any requirements on the
309 // policies that are set with setSandboxPolicy(). This means, as soon as
310 // the sandbox is active, we shouldn't be relying on libraries that could
311 // be making system calls. This, for example, means we should avoid
312 // using the heap and we should avoid using STL functions.
313 // Temporarily copy the contents of the "program" vector into a
314 // stack-allocated array.
jln (very slow on Chromium) 2012/06/12 19:16:23 Please explain further that you're trying to make
Markus (顧孟勤) 2012/06/12 19:35:05 Sure, I can add a little more to the comment :-) T
315 struct sock_filter bpf[program->size()];
316 const struct sock_fprog prog = { program->size(), bpf };
317 memcpy(bpf, &(*program)[0], sizeof(bpf));
jln (very slow on Chromium) 2012/06/12 19:16:23 Would a static_cast of program be cleaner here ?
Markus (顧孟勤) 2012/06/12 19:35:05 I am not convinced a cast would actually do the ri
jln (very slow on Chromium) 2012/06/12 20:22:51 The correct solution would be to use the new vecto
318 delete program;
319
303 // Install BPF filter program 320 // Install BPF filter program
304 const struct sock_fprog prog = { program.size(), &program[0] };
305 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || 321 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
306 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 322 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
307 goto filter_failed; 323 goto filter_failed;
308 } 324 }
309 325
310 return; 326 return;
311 } 327 }
312 328
313 void Sandbox::sigSys(int nr, siginfo_t *info, void *void_context) { 329 void Sandbox::sigSys(int nr, siginfo_t *info, void *void_context) {
314 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context) { 330 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context) {
(...skipping 25 matching lines...) Expand all
340 return; 356 return;
341 } 357 }
342 358
343 359
344 bool Sandbox::suppressLogging_ = false; 360 bool Sandbox::suppressLogging_ = false;
345 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 361 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
346 int Sandbox::proc_fd_ = -1; 362 int Sandbox::proc_fd_ = -1;
347 Sandbox::Evaluators Sandbox::evaluators_; 363 Sandbox::Evaluators Sandbox::evaluators_;
348 364
349 } // namespace 365 } // namespace
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/sandbox_bpf.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698