OLD | NEW |
| (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 #ifndef SANDBOX_IMPL_H__ | |
6 #define SANDBOX_IMPL_H__ | |
7 | |
8 #include <asm/ldt.h> | |
9 #include <errno.h> | |
10 #include <fcntl.h> | |
11 #include <limits.h> | |
12 #include <linux/prctl.h> | |
13 #include <linux/unistd.h> | |
14 #include <netinet/in.h> | |
15 #include <netinet/tcp.h> | |
16 #include <sched.h> | |
17 #include <signal.h> | |
18 #include <stdarg.h> | |
19 #include <stdio.h> | |
20 #include <stdlib.h> | |
21 #include <string.h> | |
22 #include <sys/ioctl.h> | |
23 #include <sys/mman.h> | |
24 #include <sys/ptrace.h> | |
25 #include <sys/resource.h> | |
26 #include <sys/socket.h> | |
27 #include <sys/stat.h> | |
28 #include <sys/time.h> | |
29 #include <sys/types.h> | |
30 #include <time.h> | |
31 #include <unistd.h> | |
32 | |
33 #define NOINTR_SYS(x) \ | |
34 ({ typeof(x) i__; while ((i__ = (x)) < 0 && sys.my_errno == EINTR); i__;}) | |
35 | |
36 #ifdef __cplusplus | |
37 #include <map> | |
38 #include <vector> | |
39 #include "sandbox.h" | |
40 #include "securemem.h" | |
41 #include "tls.h" | |
42 | |
43 namespace playground { | |
44 | |
45 class Sandbox { | |
46 // TODO(markus): restrict access to our private file handles | |
47 public: | |
48 enum { kMaxThreads = 100 }; | |
49 | |
50 | |
51 // There are a lot of reasons why the Seccomp sandbox might not be available. | |
52 // This could be because the kernel does not support Seccomp mode, or it | |
53 // could be because we fail to successfully rewrite all system call entry | |
54 // points. | |
55 // "proc_fd" should be a file descriptor for "/proc", or -1 if not provided | |
56 // by the caller. | |
57 static int supportsSeccompSandbox(int proc_fd) | |
58 asm("SupportsSeccompSandbox"); | |
59 | |
60 // The sandbox needs to be able to access "/proc/self/maps". If this file | |
61 // is not accessible when "startSandbox()" gets called, the caller can | |
62 // provide an already opened file descriptor by calling "setProcSelfMaps()". | |
63 // The sandbox becomes the newer owner of this file descriptor and will | |
64 // eventually close it when "startSandbox()" executes. | |
65 static void setProcSelfMaps(int proc_self_maps) | |
66 asm("SeccompSandboxSetProcSelfMaps"); | |
67 | |
68 // This is the main public entry point. It finds all system calls that | |
69 // need rewriting, sets up the resources needed by the sandbox, and | |
70 // enters Seccomp mode. | |
71 static void startSandbox() asm("StartSeccompSandbox"); | |
72 | |
73 private: | |
74 // syscall_table.c has to be implemented in C, as C++ does not support | |
75 // designated initializers for arrays. The only other alternative would be | |
76 // to have a source code generator for this table. | |
77 // | |
78 // We would still like the C source file to include our header file. This | |
79 // requires some define statements to transform C++ specific constructs to | |
80 // something that is palatable to a C compiler. | |
81 #define STATIC static | |
82 #define SecureMemArgs SecureMem::Args | |
83 // Clone() is special as it has a wrapper in syscall_table.c. The wrapper | |
84 // adds one extra argument (the pointer to the saved registers) and then | |
85 // calls playground$sandbox__clone(). | |
86 static long sandbox_clone(int flags, char* stack, int* pid, int* ctid, | |
87 void* tls, void* wrapper_sp) | |
88 asm("playground$sandbox__clone") | |
89 #if defined(__x86_64__) | |
90 __attribute__((visibility("internal"))) | |
91 #endif | |
92 ; | |
93 #else | |
94 #define STATIC | |
95 #define bool int | |
96 #define SecureMemArgs void | |
97 // This is the wrapper entry point that is found in the syscall_table. | |
98 long sandbox_clone(int flags, char* stack, int* pid, int* ctid, void* tls) | |
99 asm("playground$sandbox_clone"); | |
100 #endif | |
101 | |
102 // Entry points for sandboxed code that is attempting to make system calls | |
103 STATIC long sandbox_access(const char*, int) | |
104 asm("playground$sandbox_access"); | |
105 STATIC long sandbox_exit(int status) asm("playground$sandbox_exit"); | |
106 STATIC long sandbox_getpid() asm("playground$sandbox_getpid"); | |
107 #if defined(__NR_getsockopt) | |
108 STATIC long sandbox_getsockopt(int, int, int, void*, socklen_t*) | |
109 asm("playground$sandbox_getsockopt"); | |
110 #endif | |
111 STATIC long sandbox_gettid() asm("playground$sandbox_gettid"); | |
112 STATIC long sandbox_ioctl(int d, int req, void* arg) | |
113 asm("playground$sandbox_ioctl"); | |
114 #if defined(__NR_ipc) | |
115 STATIC long sandbox_ipc(unsigned, int, int, int, void*, long) | |
116 asm("playground$sandbox_ipc"); | |
117 #endif | |
118 STATIC long sandbox_lstat(const char* path, void* buf) | |
119 asm("playground$sandbox_lstat"); | |
120 #if defined(__NR_lstat64) | |
121 STATIC long sandbox_lstat64(const char *path, void* b) | |
122 asm("playground$sandbox_lstat64"); | |
123 #endif | |
124 STATIC long sandbox_madvise(void*, size_t, int) | |
125 asm("playground$sandbox_madvise"); | |
126 STATIC void *sandbox_mmap(void* start, size_t length, int prot, int flags, | |
127 int fd, off_t offset) | |
128 asm("playground$sandbox_mmap"); | |
129 STATIC long sandbox_mprotect(const void*, size_t, int) | |
130 asm("playground$sandbox_mprotect"); | |
131 STATIC long sandbox_munmap(void* start, size_t length) | |
132 asm("playground$sandbox_munmap"); | |
133 STATIC long sandbox_open(const char*, int, mode_t) | |
134 asm("playground$sandbox_open"); | |
135 #if defined(__NR_recvfrom) | |
136 STATIC ssize_t sandbox_recvfrom(int, void*, size_t, int, void*, socklen_t*) | |
137 asm("playground$sandbox_recvfrom"); | |
138 STATIC ssize_t sandbox_recvmsg(int, struct msghdr*, int) | |
139 asm("playground$sandbox_recvmsg"); | |
140 #endif | |
141 #if defined(__NR_rt_sigaction) | |
142 STATIC long sandbox_rt_sigaction(int, const void*, void*, size_t) | |
143 asm("playground$sandbox_rt_sigaction"); | |
144 #endif | |
145 #if defined(__NR_rt_sigprocmask) | |
146 STATIC long sandbox_rt_sigprocmask(int how, const void*, void*, size_t) | |
147 asm("playground$sandbox_rt_sigprocmask"); | |
148 #endif | |
149 #if defined(__NR_sendmsg) | |
150 STATIC size_t sandbox_sendmsg(int, const struct msghdr*, int) | |
151 asm("playground$sandbox_sendmsg"); | |
152 STATIC ssize_t sandbox_sendto(int, const void*, size_t, int, const void*, | |
153 socklen_t)asm("playground$sandbox_sendto"); | |
154 #endif | |
155 #if defined(__NR_shmat) | |
156 STATIC void* sandbox_shmat(int, const void*, int) | |
157 asm("playground$sandbox_shmat"); | |
158 STATIC long sandbox_shmctl(int, int, void*) | |
159 asm("playground$sandbox_shmctl"); | |
160 STATIC long sandbox_shmdt(const void*) asm("playground$sandbox_shmdt"); | |
161 STATIC long sandbox_shmget(int, size_t, int) | |
162 asm("playground$sandbox_shmget"); | |
163 #endif | |
164 #if defined(__NR_setsockopt) | |
165 STATIC long sandbox_setsockopt(int, int, int, const void*, socklen_t) | |
166 asm("playground$sandbox_setsockopt"); | |
167 #endif | |
168 #if defined(__NR_sigaction) | |
169 STATIC long sandbox_sigaction(int, const void*, void*) | |
170 asm("playground$sandbox_sigaction"); | |
171 #endif | |
172 #if defined(__NR_signal) | |
173 STATIC void* sandbox_signal(int, const void*) | |
174 asm("playground$sandbox_signal"); | |
175 #endif | |
176 #if defined(__NR_sigprocmask) | |
177 STATIC long sandbox_sigprocmask(int how, const void*, void*) | |
178 asm("playground$sandbox_sigprocmask"); | |
179 #endif | |
180 #if defined(__NR_socketcall) | |
181 STATIC long sandbox_socketcall(int call, void* args) | |
182 asm("playground$sandbox_socketcall"); | |
183 #endif | |
184 STATIC long sandbox_stat(const char* path, void* buf) | |
185 asm("playground$sandbox_stat"); | |
186 #if defined(__NR_stat64) | |
187 STATIC long sandbox_stat64(const char *path, void* b) | |
188 asm("playground$sandbox_stat64"); | |
189 #endif | |
190 | |
191 // Functions for system calls that need to be handled in the trusted process | |
192 STATIC bool process_access(int, int, int, int, SecureMemArgs*) | |
193 asm("playground$process_access"); | |
194 STATIC bool process_clone(int, int, int, int, SecureMemArgs*) | |
195 asm("playground$process_clone"); | |
196 STATIC bool process_exit(int, int, int, int, SecureMemArgs*) | |
197 asm("playground$process_exit"); | |
198 #if defined(__NR_getsockopt) | |
199 STATIC bool process_getsockopt(int, int, int, int, SecureMemArgs*) | |
200 asm("playground$process_getsockopt"); | |
201 #endif | |
202 STATIC bool process_ioctl(int, int, int, int, SecureMemArgs*) | |
203 asm("playground$process_ioctl"); | |
204 #if defined(__NR_ipc) | |
205 STATIC bool process_ipc(int, int, int, int, SecureMemArgs*) | |
206 asm("playground$process_ipc"); | |
207 #endif | |
208 STATIC bool process_madvise(int, int, int, int, SecureMemArgs*) | |
209 asm("playground$process_madvise"); | |
210 STATIC bool process_mmap(int, int, int, int, SecureMemArgs*) | |
211 asm("playground$process_mmap"); | |
212 STATIC bool process_mprotect(int, int, int, int, SecureMemArgs*) | |
213 asm("playground$process_mprotect"); | |
214 STATIC bool process_munmap(int, int, int, int, SecureMemArgs*) | |
215 asm("playground$process_munmap"); | |
216 STATIC bool process_open(int, int, int, int, SecureMemArgs*) | |
217 asm("playground$process_open"); | |
218 #if defined(__NR_recvfrom) | |
219 STATIC bool process_recvfrom(int, int, int, int, SecureMemArgs*) | |
220 asm("playground$process_recvfrom"); | |
221 STATIC bool process_recvmsg(int, int, int, int, SecureMemArgs*) | |
222 asm("playground$process_recvmsg"); | |
223 STATIC bool process_sendmsg(int, int, int, int, SecureMemArgs*) | |
224 asm("playground$process_sendmsg"); | |
225 STATIC bool process_sendto(int, int, int, int, SecureMemArgs*) | |
226 asm("playground$process_sendto"); | |
227 STATIC bool process_setsockopt(int, int, int, int, SecureMemArgs*) | |
228 asm("playground$process_setsockopt"); | |
229 #endif | |
230 #if defined(__NR_shmat) | |
231 STATIC bool process_shmat(int, int, int, int, SecureMemArgs*) | |
232 asm("playground$process_shmat"); | |
233 STATIC bool process_shmctl(int, int, int, int, SecureMemArgs*) | |
234 asm("playground$process_shmctl"); | |
235 STATIC bool process_shmdt(int, int, int, int, SecureMemArgs*) | |
236 asm("playground$process_shmdt"); | |
237 STATIC bool process_shmget(int, int, int, int, SecureMemArgs*) | |
238 asm("playground$process_shmget"); | |
239 #endif | |
240 STATIC bool process_sigaction(int, int, int, int, SecureMemArgs*) | |
241 asm("playground$process_sigaction"); | |
242 #if defined(__NR_socketcall) | |
243 STATIC bool process_socketcall(int, int, int, int, SecureMemArgs*) | |
244 asm("playground$process_socketcall"); | |
245 #endif | |
246 STATIC bool process_stat(int, int, int, int, SecureMemArgs*) | |
247 asm("playground$process_stat"); | |
248 | |
249 #ifdef __cplusplus | |
250 friend class Debug; | |
251 friend class Library; | |
252 friend class Maps; | |
253 friend class Mutex; | |
254 friend class SecureMem; | |
255 friend class TLS; | |
256 | |
257 // Define our own inline system calls. These calls will not be rewritten | |
258 // to point to the sandboxed wrapper functions. They thus allow us to | |
259 // make actual system calls (e.g. in the sandbox initialization code, and | |
260 // in the trusted process) | |
261 class SysCalls { | |
262 public: | |
263 #define SYS_CPLUSPLUS | |
264 #define SYS_ERRNO my_errno | |
265 #define SYS_INLINE inline | |
266 #define SYS_PREFIX -1 | |
267 #undef SYS_LINUX_SYSCALL_SUPPORT_H | |
268 #include "linux_syscall_support.h" | |
269 SysCalls() : my_errno(0) { } | |
270 int my_errno; | |
271 }; | |
272 #ifdef __NR_mmap2 | |
273 #define MMAP mmap2 | |
274 #define __NR_MMAP __NR_mmap2 | |
275 #else | |
276 #define MMAP mmap | |
277 #define __NR_MMAP __NR_mmap | |
278 #endif | |
279 | |
280 // Print an error message and terminate the program. Used for fatal errors. | |
281 static void die(const char *msg = 0) __attribute__((noreturn)) { | |
282 SysCalls sys; | |
283 if (msg) { | |
284 sys.write(2, msg, strlen(msg)); | |
285 sys.write(2, "\n", 1); | |
286 } | |
287 for (;;) { | |
288 sys.exit_group(1); | |
289 sys._exit(1); | |
290 } | |
291 } | |
292 | |
293 // Wrapper around "read()" that can deal with partial and interrupted reads | |
294 // and that does not modify the global errno variable. | |
295 static ssize_t read(SysCalls& sys, int fd, void* buf, size_t len) { | |
296 if (static_cast<ssize_t>(len) < 0) { | |
297 sys.my_errno = EINVAL; | |
298 return -1; | |
299 } | |
300 size_t offset = 0; | |
301 while (offset < len) { | |
302 ssize_t partial = | |
303 NOINTR_SYS(sys.read(fd, reinterpret_cast<char*>(buf) + offset, | |
304 len - offset)); | |
305 if (partial < 0) { | |
306 return partial; | |
307 } else if (!partial) { | |
308 break; | |
309 } | |
310 offset += partial; | |
311 } | |
312 return offset; | |
313 } | |
314 | |
315 // Wrapper around "write()" that can deal with interrupted writes and that | |
316 // does not modify the global errno variable. | |
317 static ssize_t write(SysCalls& sys, int fd, const void* buf, size_t len){ | |
318 return NOINTR_SYS(sys.write(fd, buf, len)); | |
319 } | |
320 | |
321 // Sends a file handle to another process. | |
322 // N.B. trusted_thread.cc has an assembly version of this function that | |
323 // is safe to use without a call stack. If the wire-format is changed, | |
324 /// make sure to update the assembly code. | |
325 static bool sendFd(int transport, int fd0, int fd1, const void* buf, | |
326 size_t len); | |
327 | |
328 // If getFd() fails, it will set the first valid fd slot (e.g. fd0) to | |
329 // -errno. | |
330 static bool getFd(int transport, int* fd0, int* fd1, void* buf, | |
331 size_t* len); | |
332 | |
333 // Data structures used to forward system calls to the trusted process. | |
334 struct Accept { | |
335 int sockfd; | |
336 void* addr; | |
337 socklen_t* addrlen; | |
338 } __attribute__((packed)); | |
339 | |
340 struct Accept4 { | |
341 int sockfd; | |
342 void* addr; | |
343 socklen_t* addrlen; | |
344 int flags; | |
345 } __attribute__((packed)); | |
346 | |
347 struct Access { | |
348 size_t path_length; | |
349 int mode; | |
350 } __attribute__((packed)); | |
351 | |
352 struct Bind { | |
353 int sockfd; | |
354 void* addr; | |
355 socklen_t addrlen; | |
356 } __attribute__((packed)); | |
357 | |
358 struct Clone { | |
359 int flags; | |
360 char* stack; | |
361 int* pid; | |
362 int* ctid; | |
363 void* tls; | |
364 #if defined(__x86_64__) | |
365 struct { | |
366 void* r15; | |
367 void* r14; | |
368 void* r13; | |
369 void* r12; | |
370 void* r11; | |
371 void* r10; | |
372 void* r9; | |
373 void* r8; | |
374 void* rdi; | |
375 void* rsi; | |
376 void* rdx; | |
377 void* rcx; | |
378 void* rbx; | |
379 void* rbp; | |
380 void* fake_ret; | |
381 } regs64 __attribute__((packed)); | |
382 #elif defined(__i386__) | |
383 struct { | |
384 void* ebp; | |
385 void* edi; | |
386 void* esi; | |
387 void* edx; | |
388 void* ecx; | |
389 void* ebx; | |
390 } regs32 __attribute__((packed)); | |
391 #else | |
392 #error Unsupported target platform | |
393 #endif | |
394 void* ret; | |
395 } __attribute__((packed)); | |
396 | |
397 struct Connect { | |
398 int sockfd; | |
399 void* addr; | |
400 socklen_t addrlen; | |
401 } __attribute__((packed)); | |
402 | |
403 struct GetSockName { | |
404 int sockfd; | |
405 void* name; | |
406 socklen_t* namelen; | |
407 } __attribute__((packed)); | |
408 | |
409 struct GetPeerName { | |
410 int sockfd; | |
411 void* name; | |
412 socklen_t* namelen; | |
413 } __attribute__((packed)); | |
414 | |
415 struct GetSockOpt { | |
416 int sockfd; | |
417 int level; | |
418 int optname; | |
419 void* optval; | |
420 socklen_t* optlen; | |
421 } __attribute__((packed)); | |
422 | |
423 struct IOCtl { | |
424 int d; | |
425 int req; | |
426 void *arg; | |
427 } __attribute__((packed)); | |
428 | |
429 #if defined(__NR_ipc) | |
430 struct IPC { | |
431 unsigned call; | |
432 int first; | |
433 int second; | |
434 int third; | |
435 void* ptr; | |
436 long fifth; | |
437 } __attribute__((packed)); | |
438 #endif | |
439 | |
440 struct Listen { | |
441 int sockfd; | |
442 int backlog; | |
443 } __attribute__((packed)); | |
444 | |
445 struct MAdvise { | |
446 const void* start; | |
447 size_t len; | |
448 int advice; | |
449 } __attribute__((packed)); | |
450 | |
451 struct MMap { | |
452 void* start; | |
453 size_t length; | |
454 int prot; | |
455 int flags; | |
456 int fd; | |
457 off_t offset; | |
458 } __attribute__((packed)); | |
459 | |
460 struct MProtect { | |
461 const void* addr; | |
462 size_t len; | |
463 int prot; | |
464 }; | |
465 | |
466 struct MUnmap { | |
467 void* start; | |
468 size_t length; | |
469 } __attribute__((packed)); | |
470 | |
471 struct Open { | |
472 size_t path_length; | |
473 int flags; | |
474 mode_t mode; | |
475 } __attribute__((packed)); | |
476 | |
477 struct Recv { | |
478 int sockfd; | |
479 void* buf; | |
480 size_t len; | |
481 int flags; | |
482 } __attribute__((packed)); | |
483 | |
484 struct RecvFrom { | |
485 int sockfd; | |
486 void* buf; | |
487 size_t len; | |
488 int flags; | |
489 void* from; | |
490 socklen_t *fromlen; | |
491 } __attribute__((packed)); | |
492 | |
493 struct RecvMsg { | |
494 int sockfd; | |
495 struct msghdr* msg; | |
496 int flags; | |
497 } __attribute__((packed)); | |
498 | |
499 struct Send { | |
500 int sockfd; | |
501 const void* buf; | |
502 size_t len; | |
503 int flags; | |
504 } __attribute__((packed)); | |
505 | |
506 struct SendMsg { | |
507 int sockfd; | |
508 const struct msghdr* msg; | |
509 int flags; | |
510 } __attribute__((packed)); | |
511 | |
512 struct SendTo { | |
513 int sockfd; | |
514 const void* buf; | |
515 size_t len; | |
516 int flags; | |
517 const void* to; | |
518 socklen_t tolen; | |
519 } __attribute__((packed)); | |
520 | |
521 struct SetSockOpt { | |
522 int sockfd; | |
523 int level; | |
524 int optname; | |
525 const void* optval; | |
526 socklen_t optlen; | |
527 } __attribute__((packed)); | |
528 | |
529 #if defined(__NR_shmat) | |
530 struct ShmAt { | |
531 int shmid; | |
532 const void* shmaddr; | |
533 int shmflg; | |
534 } __attribute__((packed)); | |
535 | |
536 struct ShmCtl { | |
537 int shmid; | |
538 int cmd; | |
539 void *buf; | |
540 } __attribute__((packed)); | |
541 | |
542 struct ShmDt { | |
543 const void *shmaddr; | |
544 } __attribute__((packed)); | |
545 | |
546 struct ShmGet { | |
547 int key; | |
548 size_t size; | |
549 int shmflg; | |
550 } __attribute__((packed)); | |
551 #endif | |
552 | |
553 struct ShutDown { | |
554 int sockfd; | |
555 int how; | |
556 } __attribute__((packed)); | |
557 | |
558 struct SigAction { | |
559 int sysnum; | |
560 int signum; | |
561 const SysCalls::kernel_sigaction* action; | |
562 const SysCalls::kernel_sigaction* old_action; | |
563 size_t sigsetsize; | |
564 } __attribute__((packed)); | |
565 | |
566 struct Socket { | |
567 int domain; | |
568 int type; | |
569 int protocol; | |
570 } __attribute__((packed)); | |
571 | |
572 struct SocketPair { | |
573 int domain; | |
574 int type; | |
575 int protocol; | |
576 int* pair; | |
577 } __attribute__((packed)); | |
578 | |
579 #if defined(__NR_socketcall) | |
580 struct SocketCall { | |
581 int call; | |
582 void* arg_ptr; | |
583 union { | |
584 Socket socket; | |
585 Bind bind; | |
586 Connect connect; | |
587 Listen listen; | |
588 Accept accept; | |
589 GetSockName getsockname; | |
590 GetPeerName getpeername; | |
591 SocketPair socketpair; | |
592 Send send; | |
593 Recv recv; | |
594 SendTo sendto; | |
595 RecvFrom recvfrom; | |
596 ShutDown shutdown; | |
597 SetSockOpt setsockopt; | |
598 GetSockOpt getsockopt; | |
599 SendMsg sendmsg; | |
600 RecvMsg recvmsg; | |
601 Accept4 accept4; | |
602 } args; | |
603 } __attribute__((packed)); | |
604 #endif | |
605 | |
606 struct Stat { | |
607 int sysnum; | |
608 size_t path_length; | |
609 void* buf; | |
610 } __attribute__((packed)); | |
611 | |
612 // Thread local data available from each sandboxed thread. | |
613 enum { TLS_COOKIE, TLS_TID, TLS_THREAD_FD }; | |
614 static long long cookie() { return TLS::getTLSValue<long long>(TLS_COOKIE); } | |
615 static int tid() { return TLS::getTLSValue<int>(TLS_TID); } | |
616 static int threadFdPub() { return TLS::getTLSValue<int>(TLS_THREAD_FD); } | |
617 static int processFdPub() { return processFdPub_; } | |
618 static kernel_sigset_t* signalMask() { return &getSecureMem()->signalMask; } | |
619 | |
620 // The SEGV handler knows how to handle RDTSC instructions | |
621 static void setupSignalHandlers(); | |
622 static void (*segv())(int signo, SysCalls::siginfo *context, void *unused); | |
623 | |
624 // If no specific handler has been registered for a system call, call this | |
625 // function which asks the trusted thread to perform the call. This is used | |
626 // for system calls that are not restricted. | |
627 static void* defaultSystemCallHandler(int syscallNum, void* arg0, | |
628 void* arg1, void* arg2, void* arg3, | |
629 void* arg4, void* arg5) | |
630 asm("playground$defaultSystemCallHandler") | |
631 #if defined(__x86_64__) | |
632 __attribute__((visibility("internal"))) | |
633 #endif | |
634 ; | |
635 | |
636 // Return the current secure memory structure for this thread. | |
637 static SecureMem::Args* getSecureMem(); | |
638 | |
639 // Return a secure memory structure that can be used by a newly created | |
640 // thread. | |
641 static SecureMem::Args* getNewSecureMem(); | |
642 | |
643 // This functions runs in the trusted process at startup and finds all the | |
644 // memory mappings that existed when the sandbox was first enabled. Going | |
645 // forward, all these mappings are off-limits for operations such as | |
646 // mmap(), munmap(), and mprotect(). | |
647 static int initializeProtectedMap(int fd); | |
648 | |
649 // Helper functions that allows the trusted process to get access to | |
650 // "/proc/self/maps" in the sandbox. | |
651 static void snapshotMemoryMappings(int processFd, int proc_self_maps); | |
652 | |
653 // Main loop for the trusted process. | |
654 static void trustedProcess(int parentMapsFd, int processFdPub, | |
655 int sandboxFd, int cloneFd, | |
656 SecureMem::Args* secureArena) | |
657 __attribute__((noreturn)); | |
658 | |
659 // Fork()s of the trusted process. | |
660 static SecureMem::Args* createTrustedProcess(int processFdPub, int sandboxFd, | |
661 int cloneFdPub, int cloneFd); | |
662 | |
663 // Creates the trusted thread for the initial thread, then enables | |
664 // Seccomp mode. | |
665 static void createTrustedThread(int processFdPub, int cloneFdPub, | |
666 SecureMem::Args* secureMem); | |
667 | |
668 static int proc_self_maps_; | |
669 static enum SandboxStatus { | |
670 STATUS_UNKNOWN, STATUS_UNSUPPORTED, STATUS_AVAILABLE, STATUS_ENABLED | |
671 } status_; | |
672 static int pid_; | |
673 static int processFdPub_; | |
674 static int cloneFdPub_; | |
675 | |
676 #ifdef __i386__ | |
677 struct SocketCallArgInfo; | |
678 static const struct SocketCallArgInfo socketCallArgInfo[]; | |
679 #endif | |
680 | |
681 // We always have to intercept SIGSEGV. If the application wants to set its | |
682 // own SEGV handler, we forward to it whenever necessary. | |
683 static SysCalls::kernel_sigaction sa_segv_ asm("playground$sa_segv"); | |
684 | |
685 // The syscall_mutex_ can only be directly accessed by the trusted process. | |
686 // It can be accessed by the trusted thread after fork()ing and calling | |
687 // mprotect(PROT_READ|PROT_WRITE). The mutex is used for system calls that | |
688 // require passing additional data, and that require the trusted process to | |
689 // wait until the trusted thread is done processing (e.g. exit(), clone(), | |
690 // open(), stat()) | |
691 static int syscall_mutex_ asm("playground$syscall_mutex"); | |
692 | |
693 // Available in trusted process, only | |
694 typedef std::map<void *, long> ProtectedMap; | |
695 static ProtectedMap protectedMap_; | |
696 static std::vector<SecureMem::Args*> secureMemPool_; | |
697 }; | |
698 | |
699 // If this struct is extended to contain parameters that are read by | |
700 // the trusted thread, we will have to mprotect() it to be read-only when | |
701 // starting the sandbox. However, currently it is read only by the | |
702 // trusted process, and the sandboxed process cannot change the values | |
703 // that the fork()'d trusted process sees. | |
704 struct SandboxPolicy { | |
705 bool allow_file_namespace; // Allow filename-based system calls. | |
706 }; | |
707 | |
708 extern struct SandboxPolicy g_policy; | |
709 | |
710 } // namespace | |
711 | |
712 using playground::Sandbox; | |
713 #endif // __cplusplus | |
714 | |
715 #endif // SANDBOX_IMPL_H__ | |
OLD | NEW |