| 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 |