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

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: Added comments requested by Julien 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 6
7 // The kernel gives us a sandbox, we turn it into a playground :-) 7 // 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 8 // This is version 2 of the playground; version 1 was built on top of
9 // pre-BPF seccomp mode. 9 // pre-BPF seccomp mode.
10 namespace playground2 { 10 namespace playground2 {
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 sigprocmask(SIG_UNBLOCK, &mask, NULL)) { 204 sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
205 goto filter_failed; 205 goto filter_failed;
206 } 206 }
207 207
208 // We can't handle stacked evaluators, yet. We'll get there eventually 208 // We can't handle stacked evaluators, yet. We'll get there eventually
209 // though. Hang tight. 209 // though. Hang tight.
210 if (evaluators_.size() != 1) { 210 if (evaluators_.size() != 1) {
211 die("Not implemented"); 211 die("Not implemented");
212 } 212 }
213 213
214 // Assemble the BPF filter program.
215 Program *program = new Program();
216 if (!program) {
Chris Evans 2012/06/12 20:26:26 Nit: not sure you need this, the standard c++ runt
217 die("Out of memory");
218 }
219
214 // If the architecture doesn't match SECCOMP_ARCH, disallow the 220 // If the architecture doesn't match SECCOMP_ARCH, disallow the
215 // system call. 221 // system call.
216 std::vector<struct sock_filter> program; 222 program->push_back((struct sock_filter)
217 program.push_back((struct sock_filter)
218 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch))); 223 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, arch)));
219 program.push_back((struct sock_filter) 224 program->push_back((struct sock_filter)
220 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0)); 225 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_ARCH, 1, 0));
221 226
222 // TODO: Instead of killing outright, we should raise a SIGSYS and 227 // TODO: Instead of killing outright, we should raise a SIGSYS and
223 // report a useful error message. SIGKILL cannot be trapped by the 228 // report a useful error message. SIGKILL cannot be trapped by the
224 // debugger and essentially makes the program fail in a way that is 229 // debugger and essentially makes the program fail in a way that is
225 // almost impossible to debug. 230 // almost impossible to debug.
226 program.push_back((struct sock_filter) 231 program->push_back((struct sock_filter)
227 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)); 232 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL));
228 233
229 // Grab the system call number, so that we can implement jump tables. 234 // Grab the system call number, so that we can implement jump tables.
230 program.push_back((struct sock_filter) 235 program->push_back((struct sock_filter)
231 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr))); 236 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct arch_seccomp_data, nr)));
232 237
233 // On Intel architectures, verify that system call numbers are in the 238 // On Intel architectures, verify that system call numbers are in the
234 // expected number range. The older i386 and x86-64 APIs clear bit 30 239 // expected number range. The older i386 and x86-64 APIs clear bit 30
235 // on all system calls. The newer x86-32 API always sets bit 30. 240 // on all system calls. The newer x86-32 API always sets bit 30.
236 #if defined(__i386__) || defined(__x86_64__) 241 #if defined(__i386__) || defined(__x86_64__)
237 #if defined(__x86_64__) && defined(__ILP32__) 242 #if defined(__x86_64__) && defined(__ILP32__)
238 program.push_back((struct sock_filter) 243 program->push_back((struct sock_filter)
239 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0)); 244 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 1, 0));
240 #else 245 #else
241 program.push_back((struct sock_filter) 246 program->push_back((struct sock_filter)
242 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1)); 247 BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x40000000, 0, 1));
243 #endif 248 #endif
244 // TODO: raise a suitable SIGSYS signal 249 // TODO: raise a suitable SIGSYS signal
245 program.push_back((struct sock_filter) 250 program->push_back((struct sock_filter)
246 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)); 251 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL));
247 #endif 252 #endif
248 253
249 // Evaluate all possible system calls and depending on their 254 // Evaluate all possible system calls and depending on their
250 // exit codes generate a BPF filter. 255 // exit codes generate a BPF filter.
251 // This is very inefficient right now. We need to be much smarter 256 // This is very inefficient right now. We need to be much smarter
252 // eventually. 257 // eventually.
253 // We currently incur a O(N) overhead on each system call, with N 258 // 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 259 // 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 260 // O(log_2(M)) with M being the number of system calls that need special
(...skipping 15 matching lines...) Expand all
271 if (err >= static_cast<ErrorCode>(1) && 276 if (err >= static_cast<ErrorCode>(1) &&
272 err <= static_cast<ErrorCode>(4096)) { 277 err <= static_cast<ErrorCode>(4096)) {
273 // We limit errno values to a reasonable range. In fact, the Linux ABI 278 // We limit errno values to a reasonable range. In fact, the Linux ABI
274 // doesn't support errno values outside of this range. 279 // doesn't support errno values outside of this range.
275 ret = SECCOMP_RET_ERRNO + err; 280 ret = SECCOMP_RET_ERRNO + err;
276 } else { 281 } else {
277 die("Invalid ErrorCode reported by sandbox system call evaluator"); 282 die("Invalid ErrorCode reported by sandbox system call evaluator");
278 } 283 }
279 break; 284 break;
280 } 285 }
281 program.push_back((struct sock_filter) 286 program->push_back((struct sock_filter)
282 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1)); 287 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysnum, 0, 1));
283 program.push_back((struct sock_filter) 288 program->push_back((struct sock_filter)
284 BPF_STMT(BPF_RET+BPF_K, ret)); 289 BPF_STMT(BPF_RET+BPF_K, ret));
285 } 290 }
286 291
287 // Everything that isn't allowed is forbidden. Eventually, we would 292 // Everything that isn't allowed is forbidden. Eventually, we would
288 // like to have a way to log forbidden calls, when in debug mode. 293 // like to have a way to log forbidden calls, when in debug mode.
289 // TODO: raise a suitable SIGSYS signal 294 // TODO: raise a suitable SIGSYS signal
290 program.push_back((struct sock_filter) 295 program->push_back((struct sock_filter)
291 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)); 296 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL));
292 297
298 // We want to be very careful in not imposing any requirements on the
299 // policies that are set with setSandboxPolicy(). This means, as soon as
300 // the sandbox is active, we shouldn't be relying on libraries that could
301 // be making system calls. This, for example, means we should avoid
302 // using the heap and we should avoid using STL functions.
303 // Temporarily copy the contents of the "program" vector into a
304 // stack-allocated array; and then explicitly destroy that object.
305 // This makes sure we don't ex- or implicitly call new/delete after we
306 // installed the BPF filter program in the kernel. Depending on the
307 // system memory allocator that is in effect, these operators can result
308 // in system calls to things like munmap() or brk().
309 struct sock_filter bpf[program->size()];
310 const struct sock_fprog prog = { program->size(), bpf };
311 memcpy(bpf, &(*program)[0], sizeof(bpf));
312 delete program;
313
293 // Install BPF filter program 314 // Install BPF filter program
294 const struct sock_fprog prog = { program.size(), &program[0] };
295 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || 315 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
296 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 316 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
297 goto filter_failed; 317 goto filter_failed;
298 } 318 }
299 319
300 return; 320 return;
301 } 321 }
302 322
303 void Sandbox::sigSys(int nr, siginfo_t *info, void *void_context) { 323 void Sandbox::sigSys(int nr, siginfo_t *info, void *void_context) {
304 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context) { 324 if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context) {
(...skipping 26 matching lines...) Expand all
331 } 351 }
332 352
333 353
334 bool Sandbox::suppressLogging_ = false; 354 bool Sandbox::suppressLogging_ = false;
335 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN; 355 Sandbox::SandboxStatus Sandbox::status_ = STATUS_UNKNOWN;
336 int Sandbox::proc_fd_ = -1; 356 int Sandbox::proc_fd_ = -1;
337 std::vector<std::pair<Sandbox::EvaluateSyscall, 357 std::vector<std::pair<Sandbox::EvaluateSyscall,
338 Sandbox::EvaluateArguments> > Sandbox::evaluators_; 358 Sandbox::EvaluateArguments> > Sandbox::evaluators_;
339 359
340 } // namespace 360 } // 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