diff options
Diffstat (limited to 'sandbox/linux/seccomp/sandbox_impl.h')
-rw-r--r-- | sandbox/linux/seccomp/sandbox_impl.h | 715 |
1 files changed, 0 insertions, 715 deletions
diff --git a/sandbox/linux/seccomp/sandbox_impl.h b/sandbox/linux/seccomp/sandbox_impl.h deleted file mode 100644 index 3e99a5510..0000000 --- a/sandbox/linux/seccomp/sandbox_impl.h +++ /dev/null @@ -1,715 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_IMPL_H__ -#define SANDBOX_IMPL_H__ - -#include <asm/ldt.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <linux/prctl.h> -#include <linux/unistd.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <sched.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/ptrace.h> -#include <sys/resource.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> - -#define NOINTR_SYS(x) \ - ({ typeof(x) i__; while ((i__ = (x)) < 0 && sys.my_errno == EINTR); i__;}) - -#ifdef __cplusplus -#include <map> -#include <vector> -#include "sandbox.h" -#include "securemem.h" -#include "tls.h" - -namespace playground { - -class Sandbox { - // TODO(markus): restrict access to our private file handles - public: - enum { kMaxThreads = 100 }; - - - // There are a lot of reasons why the Seccomp sandbox might not be available. - // This could be because the kernel does not support Seccomp mode, or it - // could be because we fail to successfully rewrite all system call entry - // points. - // "proc_fd" should be a file descriptor for "/proc", or -1 if not provided - // by the caller. - static int supportsSeccompSandbox(int proc_fd) - asm("SupportsSeccompSandbox"); - - // The sandbox needs to be able to access "/proc/self/maps". If this file - // is not accessible when "startSandbox()" gets called, the caller can - // provide an already opened file descriptor by calling "setProcSelfMaps()". - // The sandbox becomes the newer owner of this file descriptor and will - // eventually close it when "startSandbox()" executes. - static void setProcSelfMaps(int proc_self_maps) - asm("SeccompSandboxSetProcSelfMaps"); - - // This is the main public entry point. It finds all system calls that - // need rewriting, sets up the resources needed by the sandbox, and - // enters Seccomp mode. - static void startSandbox() asm("StartSeccompSandbox"); - - private: -// syscall_table.c has to be implemented in C, as C++ does not support -// designated initializers for arrays. The only other alternative would be -// to have a source code generator for this table. -// -// We would still like the C source file to include our header file. This -// requires some define statements to transform C++ specific constructs to -// something that is palatable to a C compiler. -#define STATIC static -#define SecureMemArgs SecureMem::Args - // Clone() is special as it has a wrapper in syscall_table.c. The wrapper - // adds one extra argument (the pointer to the saved registers) and then - // calls playground$sandbox__clone(). - static long sandbox_clone(int flags, char* stack, int* pid, int* ctid, - void* tls, void* wrapper_sp) - asm("playground$sandbox__clone") - #if defined(__x86_64__) - __attribute__((visibility("internal"))) -#endif - ; -#else -#define STATIC -#define bool int -#define SecureMemArgs void - // This is the wrapper entry point that is found in the syscall_table. - long sandbox_clone(int flags, char* stack, int* pid, int* ctid, void* tls) - asm("playground$sandbox_clone"); -#endif - - // Entry points for sandboxed code that is attempting to make system calls - STATIC long sandbox_access(const char*, int) - asm("playground$sandbox_access"); - STATIC long sandbox_exit(int status) asm("playground$sandbox_exit"); - STATIC long sandbox_getpid() asm("playground$sandbox_getpid"); - #if defined(__NR_getsockopt) - STATIC long sandbox_getsockopt(int, int, int, void*, socklen_t*) - asm("playground$sandbox_getsockopt"); - #endif - STATIC long sandbox_gettid() asm("playground$sandbox_gettid"); - STATIC long sandbox_ioctl(int d, int req, void* arg) - asm("playground$sandbox_ioctl"); - #if defined(__NR_ipc) - STATIC long sandbox_ipc(unsigned, int, int, int, void*, long) - asm("playground$sandbox_ipc"); - #endif - STATIC long sandbox_lstat(const char* path, void* buf) - asm("playground$sandbox_lstat"); - #if defined(__NR_lstat64) - STATIC long sandbox_lstat64(const char *path, void* b) - asm("playground$sandbox_lstat64"); - #endif - STATIC long sandbox_madvise(void*, size_t, int) - asm("playground$sandbox_madvise"); - STATIC void *sandbox_mmap(void* start, size_t length, int prot, int flags, - int fd, off_t offset) - asm("playground$sandbox_mmap"); - STATIC long sandbox_mprotect(const void*, size_t, int) - asm("playground$sandbox_mprotect"); - STATIC long sandbox_munmap(void* start, size_t length) - asm("playground$sandbox_munmap"); - STATIC long sandbox_open(const char*, int, mode_t) - asm("playground$sandbox_open"); - #if defined(__NR_recvfrom) - STATIC ssize_t sandbox_recvfrom(int, void*, size_t, int, void*, socklen_t*) - asm("playground$sandbox_recvfrom"); - STATIC ssize_t sandbox_recvmsg(int, struct msghdr*, int) - asm("playground$sandbox_recvmsg"); - #endif - #if defined(__NR_rt_sigaction) - STATIC long sandbox_rt_sigaction(int, const void*, void*, size_t) - asm("playground$sandbox_rt_sigaction"); - #endif - #if defined(__NR_rt_sigprocmask) - STATIC long sandbox_rt_sigprocmask(int how, const void*, void*, size_t) - asm("playground$sandbox_rt_sigprocmask"); - #endif - #if defined(__NR_sendmsg) - STATIC size_t sandbox_sendmsg(int, const struct msghdr*, int) - asm("playground$sandbox_sendmsg"); - STATIC ssize_t sandbox_sendto(int, const void*, size_t, int, const void*, - socklen_t)asm("playground$sandbox_sendto"); - #endif - #if defined(__NR_shmat) - STATIC void* sandbox_shmat(int, const void*, int) - asm("playground$sandbox_shmat"); - STATIC long sandbox_shmctl(int, int, void*) - asm("playground$sandbox_shmctl"); - STATIC long sandbox_shmdt(const void*) asm("playground$sandbox_shmdt"); - STATIC long sandbox_shmget(int, size_t, int) - asm("playground$sandbox_shmget"); - #endif - #if defined(__NR_setsockopt) - STATIC long sandbox_setsockopt(int, int, int, const void*, socklen_t) - asm("playground$sandbox_setsockopt"); - #endif - #if defined(__NR_sigaction) - STATIC long sandbox_sigaction(int, const void*, void*) - asm("playground$sandbox_sigaction"); - #endif - #if defined(__NR_signal) - STATIC void* sandbox_signal(int, const void*) - asm("playground$sandbox_signal"); - #endif - #if defined(__NR_sigprocmask) - STATIC long sandbox_sigprocmask(int how, const void*, void*) - asm("playground$sandbox_sigprocmask"); - #endif - #if defined(__NR_socketcall) - STATIC long sandbox_socketcall(int call, void* args) - asm("playground$sandbox_socketcall"); - #endif - STATIC long sandbox_stat(const char* path, void* buf) - asm("playground$sandbox_stat"); - #if defined(__NR_stat64) - STATIC long sandbox_stat64(const char *path, void* b) - asm("playground$sandbox_stat64"); - #endif - - // Functions for system calls that need to be handled in the trusted process - STATIC bool process_access(int, int, int, int, SecureMemArgs*) - asm("playground$process_access"); - STATIC bool process_clone(int, int, int, int, SecureMemArgs*) - asm("playground$process_clone"); - STATIC bool process_exit(int, int, int, int, SecureMemArgs*) - asm("playground$process_exit"); - #if defined(__NR_getsockopt) - STATIC bool process_getsockopt(int, int, int, int, SecureMemArgs*) - asm("playground$process_getsockopt"); - #endif - STATIC bool process_ioctl(int, int, int, int, SecureMemArgs*) - asm("playground$process_ioctl"); - #if defined(__NR_ipc) - STATIC bool process_ipc(int, int, int, int, SecureMemArgs*) - asm("playground$process_ipc"); - #endif - STATIC bool process_madvise(int, int, int, int, SecureMemArgs*) - asm("playground$process_madvise"); - STATIC bool process_mmap(int, int, int, int, SecureMemArgs*) - asm("playground$process_mmap"); - STATIC bool process_mprotect(int, int, int, int, SecureMemArgs*) - asm("playground$process_mprotect"); - STATIC bool process_munmap(int, int, int, int, SecureMemArgs*) - asm("playground$process_munmap"); - STATIC bool process_open(int, int, int, int, SecureMemArgs*) - asm("playground$process_open"); - #if defined(__NR_recvfrom) - STATIC bool process_recvfrom(int, int, int, int, SecureMemArgs*) - asm("playground$process_recvfrom"); - STATIC bool process_recvmsg(int, int, int, int, SecureMemArgs*) - asm("playground$process_recvmsg"); - STATIC bool process_sendmsg(int, int, int, int, SecureMemArgs*) - asm("playground$process_sendmsg"); - STATIC bool process_sendto(int, int, int, int, SecureMemArgs*) - asm("playground$process_sendto"); - STATIC bool process_setsockopt(int, int, int, int, SecureMemArgs*) - asm("playground$process_setsockopt"); - #endif - #if defined(__NR_shmat) - STATIC bool process_shmat(int, int, int, int, SecureMemArgs*) - asm("playground$process_shmat"); - STATIC bool process_shmctl(int, int, int, int, SecureMemArgs*) - asm("playground$process_shmctl"); - STATIC bool process_shmdt(int, int, int, int, SecureMemArgs*) - asm("playground$process_shmdt"); - STATIC bool process_shmget(int, int, int, int, SecureMemArgs*) - asm("playground$process_shmget"); - #endif - STATIC bool process_sigaction(int, int, int, int, SecureMemArgs*) - asm("playground$process_sigaction"); - #if defined(__NR_socketcall) - STATIC bool process_socketcall(int, int, int, int, SecureMemArgs*) - asm("playground$process_socketcall"); - #endif - STATIC bool process_stat(int, int, int, int, SecureMemArgs*) - asm("playground$process_stat"); - -#ifdef __cplusplus - friend class Debug; - friend class Library; - friend class Maps; - friend class Mutex; - friend class SecureMem; - friend class TLS; - - // Define our own inline system calls. These calls will not be rewritten - // to point to the sandboxed wrapper functions. They thus allow us to - // make actual system calls (e.g. in the sandbox initialization code, and - // in the trusted process) - class SysCalls { - public: - #define SYS_CPLUSPLUS - #define SYS_ERRNO my_errno - #define SYS_INLINE inline - #define SYS_PREFIX -1 - #undef SYS_LINUX_SYSCALL_SUPPORT_H - #include "linux_syscall_support.h" - SysCalls() : my_errno(0) { } - int my_errno; - }; - #ifdef __NR_mmap2 - #define MMAP mmap2 - #define __NR_MMAP __NR_mmap2 - #else - #define MMAP mmap - #define __NR_MMAP __NR_mmap - #endif - - // Print an error message and terminate the program. Used for fatal errors. - static void die(const char *msg = 0) __attribute__((noreturn)) { - SysCalls sys; - if (msg) { - sys.write(2, msg, strlen(msg)); - sys.write(2, "\n", 1); - } - for (;;) { - sys.exit_group(1); - sys._exit(1); - } - } - - // Wrapper around "read()" that can deal with partial and interrupted reads - // and that does not modify the global errno variable. - static ssize_t read(SysCalls& sys, int fd, void* buf, size_t len) { - if (static_cast<ssize_t>(len) < 0) { - sys.my_errno = EINVAL; - return -1; - } - size_t offset = 0; - while (offset < len) { - ssize_t partial = - NOINTR_SYS(sys.read(fd, reinterpret_cast<char*>(buf) + offset, - len - offset)); - if (partial < 0) { - return partial; - } else if (!partial) { - break; - } - offset += partial; - } - return offset; - } - - // Wrapper around "write()" that can deal with interrupted writes and that - // does not modify the global errno variable. - static ssize_t write(SysCalls& sys, int fd, const void* buf, size_t len){ - return NOINTR_SYS(sys.write(fd, buf, len)); - } - - // Sends a file handle to another process. - // N.B. trusted_thread.cc has an assembly version of this function that - // is safe to use without a call stack. If the wire-format is changed, - /// make sure to update the assembly code. - static bool sendFd(int transport, int fd0, int fd1, const void* buf, - size_t len); - - // If getFd() fails, it will set the first valid fd slot (e.g. fd0) to - // -errno. - static bool getFd(int transport, int* fd0, int* fd1, void* buf, - size_t* len); - - // Data structures used to forward system calls to the trusted process. - struct Accept { - int sockfd; - void* addr; - socklen_t* addrlen; - } __attribute__((packed)); - - struct Accept4 { - int sockfd; - void* addr; - socklen_t* addrlen; - int flags; - } __attribute__((packed)); - - struct Access { - size_t path_length; - int mode; - } __attribute__((packed)); - - struct Bind { - int sockfd; - void* addr; - socklen_t addrlen; - } __attribute__((packed)); - - struct Clone { - int flags; - char* stack; - int* pid; - int* ctid; - void* tls; - #if defined(__x86_64__) - struct { - void* r15; - void* r14; - void* r13; - void* r12; - void* r11; - void* r10; - void* r9; - void* r8; - void* rdi; - void* rsi; - void* rdx; - void* rcx; - void* rbx; - void* rbp; - void* fake_ret; - } regs64 __attribute__((packed)); - #elif defined(__i386__) - struct { - void* ebp; - void* edi; - void* esi; - void* edx; - void* ecx; - void* ebx; - } regs32 __attribute__((packed)); - #else - #error Unsupported target platform - #endif - void* ret; - } __attribute__((packed)); - - struct Connect { - int sockfd; - void* addr; - socklen_t addrlen; - } __attribute__((packed)); - - struct GetSockName { - int sockfd; - void* name; - socklen_t* namelen; - } __attribute__((packed)); - - struct GetPeerName { - int sockfd; - void* name; - socklen_t* namelen; - } __attribute__((packed)); - - struct GetSockOpt { - int sockfd; - int level; - int optname; - void* optval; - socklen_t* optlen; - } __attribute__((packed)); - - struct IOCtl { - int d; - int req; - void *arg; - } __attribute__((packed)); - - #if defined(__NR_ipc) - struct IPC { - unsigned call; - int first; - int second; - int third; - void* ptr; - long fifth; - } __attribute__((packed)); - #endif - - struct Listen { - int sockfd; - int backlog; - } __attribute__((packed)); - - struct MAdvise { - const void* start; - size_t len; - int advice; - } __attribute__((packed)); - - struct MMap { - void* start; - size_t length; - int prot; - int flags; - int fd; - off_t offset; - } __attribute__((packed)); - - struct MProtect { - const void* addr; - size_t len; - int prot; - }; - - struct MUnmap { - void* start; - size_t length; - } __attribute__((packed)); - - struct Open { - size_t path_length; - int flags; - mode_t mode; - } __attribute__((packed)); - - struct Recv { - int sockfd; - void* buf; - size_t len; - int flags; - } __attribute__((packed)); - - struct RecvFrom { - int sockfd; - void* buf; - size_t len; - int flags; - void* from; - socklen_t *fromlen; - } __attribute__((packed)); - - struct RecvMsg { - int sockfd; - struct msghdr* msg; - int flags; - } __attribute__((packed)); - - struct Send { - int sockfd; - const void* buf; - size_t len; - int flags; - } __attribute__((packed)); - - struct SendMsg { - int sockfd; - const struct msghdr* msg; - int flags; - } __attribute__((packed)); - - struct SendTo { - int sockfd; - const void* buf; - size_t len; - int flags; - const void* to; - socklen_t tolen; - } __attribute__((packed)); - - struct SetSockOpt { - int sockfd; - int level; - int optname; - const void* optval; - socklen_t optlen; - } __attribute__((packed)); - - #if defined(__NR_shmat) - struct ShmAt { - int shmid; - const void* shmaddr; - int shmflg; - } __attribute__((packed)); - - struct ShmCtl { - int shmid; - int cmd; - void *buf; - } __attribute__((packed)); - - struct ShmDt { - const void *shmaddr; - } __attribute__((packed)); - - struct ShmGet { - int key; - size_t size; - int shmflg; - } __attribute__((packed)); - #endif - - struct ShutDown { - int sockfd; - int how; - } __attribute__((packed)); - - struct SigAction { - int sysnum; - int signum; - const SysCalls::kernel_sigaction* action; - const SysCalls::kernel_sigaction* old_action; - size_t sigsetsize; - } __attribute__((packed)); - - struct Socket { - int domain; - int type; - int protocol; - } __attribute__((packed)); - - struct SocketPair { - int domain; - int type; - int protocol; - int* pair; - } __attribute__((packed)); - - #if defined(__NR_socketcall) - struct SocketCall { - int call; - void* arg_ptr; - union { - Socket socket; - Bind bind; - Connect connect; - Listen listen; - Accept accept; - GetSockName getsockname; - GetPeerName getpeername; - SocketPair socketpair; - Send send; - Recv recv; - SendTo sendto; - RecvFrom recvfrom; - ShutDown shutdown; - SetSockOpt setsockopt; - GetSockOpt getsockopt; - SendMsg sendmsg; - RecvMsg recvmsg; - Accept4 accept4; - } args; - } __attribute__((packed)); - #endif - - struct Stat { - int sysnum; - size_t path_length; - void* buf; - } __attribute__((packed)); - - // Thread local data available from each sandboxed thread. - enum { TLS_COOKIE, TLS_TID, TLS_THREAD_FD }; - static long long cookie() { return TLS::getTLSValue<long long>(TLS_COOKIE); } - static int tid() { return TLS::getTLSValue<int>(TLS_TID); } - static int threadFdPub() { return TLS::getTLSValue<int>(TLS_THREAD_FD); } - static int processFdPub() { return processFdPub_; } - static kernel_sigset_t* signalMask() { return &getSecureMem()->signalMask; } - - // The SEGV handler knows how to handle RDTSC instructions - static void setupSignalHandlers(); - static void (*segv())(int signo, SysCalls::siginfo *context, void *unused); - - // If no specific handler has been registered for a system call, call this - // function which asks the trusted thread to perform the call. This is used - // for system calls that are not restricted. - static void* defaultSystemCallHandler(int syscallNum, void* arg0, - void* arg1, void* arg2, void* arg3, - void* arg4, void* arg5) - asm("playground$defaultSystemCallHandler") - #if defined(__x86_64__) - __attribute__((visibility("internal"))) - #endif - ; - - // Return the current secure memory structure for this thread. - static SecureMem::Args* getSecureMem(); - - // Return a secure memory structure that can be used by a newly created - // thread. - static SecureMem::Args* getNewSecureMem(); - - // This functions runs in the trusted process at startup and finds all the - // memory mappings that existed when the sandbox was first enabled. Going - // forward, all these mappings are off-limits for operations such as - // mmap(), munmap(), and mprotect(). - static int initializeProtectedMap(int fd); - - // Helper functions that allows the trusted process to get access to - // "/proc/self/maps" in the sandbox. - static void snapshotMemoryMappings(int processFd, int proc_self_maps); - - // Main loop for the trusted process. - static void trustedProcess(int parentMapsFd, int processFdPub, - int sandboxFd, int cloneFd, - SecureMem::Args* secureArena) - __attribute__((noreturn)); - - // Fork()s of the trusted process. - static SecureMem::Args* createTrustedProcess(int processFdPub, int sandboxFd, - int cloneFdPub, int cloneFd); - - // Creates the trusted thread for the initial thread, then enables - // Seccomp mode. - static void createTrustedThread(int processFdPub, int cloneFdPub, - SecureMem::Args* secureMem); - - static int proc_self_maps_; - static enum SandboxStatus { - STATUS_UNKNOWN, STATUS_UNSUPPORTED, STATUS_AVAILABLE, STATUS_ENABLED - } status_; - static int pid_; - static int processFdPub_; - static int cloneFdPub_; - - #ifdef __i386__ - struct SocketCallArgInfo; - static const struct SocketCallArgInfo socketCallArgInfo[]; - #endif - - // We always have to intercept SIGSEGV. If the application wants to set its - // own SEGV handler, we forward to it whenever necessary. - static SysCalls::kernel_sigaction sa_segv_ asm("playground$sa_segv"); - - // The syscall_mutex_ can only be directly accessed by the trusted process. - // It can be accessed by the trusted thread after fork()ing and calling - // mprotect(PROT_READ|PROT_WRITE). The mutex is used for system calls that - // require passing additional data, and that require the trusted process to - // wait until the trusted thread is done processing (e.g. exit(), clone(), - // open(), stat()) - static int syscall_mutex_ asm("playground$syscall_mutex"); - - // Available in trusted process, only - typedef std::map<void *, long> ProtectedMap; - static ProtectedMap protectedMap_; - static std::vector<SecureMem::Args*> secureMemPool_; -}; - -// If this struct is extended to contain parameters that are read by -// the trusted thread, we will have to mprotect() it to be read-only when -// starting the sandbox. However, currently it is read only by the -// trusted process, and the sandboxed process cannot change the values -// that the fork()'d trusted process sees. -struct SandboxPolicy { - bool allow_file_namespace; // Allow filename-based system calls. -}; - -extern struct SandboxPolicy g_policy; - -} // namespace - -using playground::Sandbox; -#endif // __cplusplus - -#endif // SANDBOX_IMPL_H__ |