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

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

Issue 10546041: Added a new Verifier class to the BPF compiler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Typo 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
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 7
7 // 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 :-)
8 // 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
9 // pre-BPF seccomp mode. 10 // pre-BPF seccomp mode.
10 namespace playground2 { 11 namespace playground2 {
11 12
12 Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) { 13 Sandbox::ErrorCode Sandbox::probeEvaluator(int signo) {
13 switch (signo) { 14 switch (signo) {
14 case __NR_getpid: 15 case __NR_getpid:
15 // Return EPERM so that we can check that the filter actually ran. 16 // Return EPERM so that we can check that the filter actually ran.
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 249
249 // Evaluate all possible system calls and depending on their 250 // Evaluate all possible system calls and depending on their
250 // exit codes generate a BPF filter. 251 // exit codes generate a BPF filter.
251 // This is very inefficient right now. We need to be much smarter 252 // This is very inefficient right now. We need to be much smarter
252 // eventually. 253 // eventually.
253 // We currently incur a O(N) overhead on each system call, with N 254 // We currently incur a O(N) overhead on each system call, with N
254 // being the number of system calls. It is easy to get this down to 255 // being the number of system calls. It is easy to get this down to
255 // O(log_2(M)) with M being the number of system calls that need special 256 // O(log_2(M)) with M being the number of system calls that need special
256 // treatment. 257 // treatment.
257 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first; 258 EvaluateSyscall evaluateSyscall = evaluators_.begin()->first;
258 for (int sysnum = MIN_SYSCALL; sysnum <= MAX_SYSCALL; ++sysnum) { 259 for (int sysnum = MIN_SYSCALL; sysnum <= MAX_SYSCALL+1; ++sysnum) {
Chris Evans 2012/06/11 19:20:41 Should sysnum be signed?
Markus (顧孟勤) 2012/06/11 20:58:43 Yes, a future change list is actually changing it
259 ErrorCode err = evaluateSyscall(sysnum); 260 ErrorCode err = evaluateSyscall(sysnum);
260 int ret; 261 int ret;
261 switch (err) { 262 switch (err) {
262 case SB_INSPECT_ARG_1...SB_INSPECT_ARG_6: 263 case SB_INSPECT_ARG_1...SB_INSPECT_ARG_6:
263 die("Not implemented"); 264 die("Not implemented");
264 case SB_TRAP: 265 case SB_TRAP:
265 ret = SECCOMP_RET_TRAP; 266 ret = SECCOMP_RET_TRAP;
266 break; 267 break;
267 case SB_ALLOWED: 268 case SB_ALLOWED:
268 ret = SECCOMP_RET_ALLOW; 269 ret = SECCOMP_RET_ALLOW;
269 break; 270 break;
270 default: 271 default:
271 if (err >= static_cast<ErrorCode>(1) && 272 if (err >= static_cast<ErrorCode>(1) &&
272 err <= static_cast<ErrorCode>(4096)) { 273 err <= static_cast<ErrorCode>(4096)) {
273 // We limit errno values to a reasonable range. In fact, the Linux ABI 274 // We limit errno values to a reasonable range. In fact, the Linux ABI
274 // doesn't support errno values outside of this range. 275 // doesn't support errno values outside of this range.
275 ret = SECCOMP_RET_ERRNO + err; 276 ret = SECCOMP_RET_ERRNO + err;
276 } else { 277 } else {
277 die("Invalid ErrorCode reported by sandbox system call evaluator"); 278 die("Invalid ErrorCode reported by sandbox system call evaluator");
278 } 279 }
279 break; 280 break;
280 } 281 }
281 program.push_back((struct sock_filter) 282 if (sysnum <= MAX_SYSCALL) {
282 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1)); 283 // 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
285 // MAX_SYSCALL.
286 // In other words, the very last iteration in our loop becomes the
287 // fallback case and we don't need to do any comparisons.
288 program.push_back((struct sock_filter)
289 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1));
290 }
283 program.push_back((struct sock_filter) 291 program.push_back((struct sock_filter)
284 BPF_STMT(BPF_RET+BPF_K, ret)); 292 BPF_STMT(BPF_RET+BPF_K, ret));
285 } 293 }
286 294
287 // Everything that isn't allowed is forbidden. Eventually, we would 295 // Make sure compilation resulted in BPF program that executes
288 // like to have a way to log forbidden calls, when in debug mode. 296 // correctly. Otherwise, there is an internal error in our BPF compiler.
289 // TODO: raise a suitable SIGSYS signal 297 // There is really nothing the caller can do until the bug is fixed.
290 program.push_back((struct sock_filter) 298 const char *err;
Chris Evans 2012/06/11 19:20:41 Initialize to NULL for safety, since it's a pointe
Markus (顧孟勤) 2012/06/11 20:58:43 Done.
291 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)); 299 if (!Verifier::verifyBPF(program, evaluators_, &err)) {
Chris Evans 2012/06/11 19:20:41 I think we should only do this step under #ifdef D
Markus (顧孟勤) 2012/06/11 20:58:43 I am on the fence. Execution time various somewher
300 die(err);
301 }
292 302
293 // Install BPF filter program 303 // Install BPF filter program
294 const struct sock_fprog prog = { program.size(), &program[0] }; 304 const struct sock_fprog prog = { program.size(), &program[0] };
295 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || 305 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
296 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 306 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
297 goto filter_failed; 307 goto filter_failed;
298 } 308 }
299 309
300 return; 310 return;
301 } 311 }
(...skipping 25 matching lines...) Expand all
327 337
328 ctx->uc_mcontext.gregs[REG_RESULT] = reinterpret_cast<greg_t>(rc); 338 ctx->uc_mcontext.gregs[REG_RESULT] = reinterpret_cast<greg_t>(rc);
329 errno = old_errno; 339 errno = old_errno;
330 return; 340 return;
331 } 341 }
332 342
333 343
334 bool Sandbox::suppressLogging_ = false; 344 bool Sandbox::suppressLogging_ = false;
335 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 345 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
336 int Sandbox::proc_fd_ = -1; 346 int Sandbox::proc_fd_ = -1;
337 std::vector<std::pair<Sandbox::EvaluateSyscall, 347 Sandbox::Evaluators Sandbox::evaluators_;
338 Sandbox::EvaluateArguments> > Sandbox::evaluators_;
339 348
340 } // namespace 349 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698