diff options
Diffstat (limited to 'content/common/sandbox_seccomp_bpf_linux.cc')
-rw-r--r-- | content/common/sandbox_seccomp_bpf_linux.cc | 816 |
1 files changed, 720 insertions, 96 deletions
diff --git a/content/common/sandbox_seccomp_bpf_linux.cc b/content/common/sandbox_seccomp_bpf_linux.cc index be331c4..cbea595 100644 --- a/content/common/sandbox_seccomp_bpf_linux.cc +++ b/content/common/sandbox_seccomp_bpf_linux.cc @@ -43,18 +43,6 @@ inline bool IsChromeOS() { #endif } -void LogSandboxStarted(const std::string& sandbox_name, - const std::string& process_type) { - const std::string activated_sandbox = - "Activated " + sandbox_name + " sandbox for process type: " + - process_type + "."; - if (IsChromeOS()) { - LOG(WARNING) << activated_sandbox; - } else { - VLOG(1) << activated_sandbox; - } -} - intptr_t CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux) { int syscall = args.nr; if (syscall >= 1024) @@ -79,50 +67,6 @@ intptr_t CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux) { _exit(1); } -// TODO(jln) we need to restrict the first parameter! -bool IsKillSyscall(int sysno) { - switch (sysno) { - case __NR_kill: - case __NR_tkill: - case __NR_tgkill: - return true; - default: - return false; - } -} - -bool IsGettimeSyscall(int sysno) { - switch (sysno) { - case __NR_clock_gettime: - case __NR_gettimeofday: - case __NR_time: - return true; - default: - return false; - } -} - -bool IsFileSystemSyscall(int sysno) { - switch (sysno) { - case __NR_open: - case __NR_openat: - case __NR_execve: - case __NR_access: - case __NR_mkdir: - case __NR_mkdirat: - case __NR_readlink: - case __NR_readlinkat: - case __NR_stat: - case __NR_lstat: - case __NR_chdir: - case __NR_mknod: - case __NR_mknodat: - return true; - default: - return false; - } -} - bool IsAcceleratedVideoDecodeEnabled() { // Accelerated video decode is currently enabled on Chrome OS, // but not on Linux: crbug.com/137247. @@ -204,60 +148,731 @@ intptr_t GpuOpenSIGSYS_Handler(const struct arch_seccomp_data& args, } #if defined(__x86_64__) -// x86_64 only because it references system calls that are multiplexed on IA32. -bool IsGpuAndFlashPolicyAllowed_x86_64(int sysno) { + +// The functions below cover all existing x86_64 system calls. +// The implicitly defined sets form a partition of the sets of +// system calls. + +// TODO(jln) we need to restrict the first parameter! +bool IsKillSyscall(int sysno) { switch (sysno) { - case __NR_brk: - case __NR_clone: // TODO(jln) restrict flags. - case __NR_close: - case __NR_dup: - case __NR_epoll_create: - case __NR_epoll_ctl: - case __NR_epoll_wait: - case __NR_exit: - case __NR_exit_group: - case __NR_fcntl: + case __NR_kill: + case __NR_tkill: + case __NR_tgkill: + return true; + default: + return false; + } +} + +bool IsAllowedGettimeSyscall(int sysno) { + switch (sysno) { + // case __NR_clock_getres: + case __NR_clock_gettime: + // case __NR_clock_nanosleep: + case __NR_gettimeofday: + case __NR_time: + return true; + case __NR_adjtimex: // Privileged. + case __NR_settimeofday: // Privileged. + case __NR_clock_adjtime: // Privileged. + case __NR_clock_settime: // Privileged. + default: + return false; + } +} + +bool IsAmbientFileSystemSyscall(int sysno) { + switch (sysno) { + // case __NR_getcwd: + case __NR_chdir: + // case __NR_fchdir: + // case __NR_umask: + return true; + default: + return false; + } +} + +// System calls that directly access the file system. They might aquire +// a new file descriptor or otherwise perform an operation directly +// via a path. +// For many, EPERM is a valid errno, but not for all of them. +bool IsFileSystemSyscall(int sysno) { + switch (sysno) { + case __NR_access: + // case __NR_chmod: + // case __NR_chown: + // case __NR_creat: + case __NR_execve: + // case __NR_faccessat: + // case __NR_fchmodat: + // case __NR_fchownat: // Should be called chownat ? + // case __NR_futimesat: // Should be called utimesat ? + // case __NR_getdents: + // case __NR_getdents64: + // case __NR_lchown: + // case __NR_link: + // case __NR_linkat: + // case __NR_lookup_dcookie: + case __NR_lstat: + case __NR_mkdir: + case __NR_mkdirat: + case __NR_mknod: + case __NR_mknodat: + // case __NR_newfstatat: // Should be called statat ? + case __NR_open: + case __NR_openat: + case __NR_readlink: + case __NR_readlinkat: + // case __NR_rename: + // case __NR_renameat: + // case __NR_rmdir: + case __NR_stat: + // case __NR_statfs: + // case __NR_symlink: + // case __NR_symlinkat: + // case __NR_truncate: + // case __NR_unlink: + // case __NR_unlinkat: + // case __NR_uselib: + // case __NR_ustat: // Deprecated. + // case __NR_utime: + // case __NR_utimensat: // New. + // case __NR_utimes: + return true; + default: + return false; + } +} + +bool IsAllowedFileSystemCapabilitySyscall(int sysno) { + switch (sysno) { + // case __NR_fadvise64: + // case __NR_flock: case __NR_fstat: - case __NR_futex: + // case __NR_fstatfs: // Give information about the whole filesystem. + // case __NR_fsync: + // case __NR_fdatasync: + // case __NR_sync_file_range: + return true; + case __NR_fallocate: + case __NR_fchmod: + case __NR_fchown: + case __NR_ftruncate: + default: + return false; + } +} + +bool IsGetProcessIdSyscall(int sysno) { + switch (sysno) { + // case __NR_capget: case __NR_getegid: case __NR_geteuid: case __NR_getgid: + // case __NR_getgroups: + // case __NR_getpid: + // case __NR_getppid: + // case __NR_getresgid: + // case __NR_getresuid: + // case __NR_getsid: case __NR_gettid: case __NR_getuid: - case __NR_lseek: + return true; + default: + return false; + } +} + +bool IsProcessPrivilegeChange(int sysno) { + switch (sysno) { + case __NR_capset: + case __NR_ioperm: // Intel privilege. + case __NR_iopl: // Intel privilege. + case __NR_setfsgid: + case __NR_setfsuid: + case __NR_setgid: + case __NR_setgroups: + case __NR_setregid: + case __NR_setresgid: + case __NR_setresuid: + case __NR_setreuid: + case __NR_setuid: + return true; + default: + return false; + } +} + +bool IsProcessGroupOrSession(int sysno) { + switch (sysno) { + case __NR_setpgid: + case __NR_getpgrp: + case __NR_setsid: + case __NR_getpgid: + return true; + default: + return false; + } +} + +bool IsAllowedSignalHandling(int sysno) { + switch (sysno) { + case __NR_rt_sigaction: + // case __NR_rt_sigpending: + case __NR_rt_sigprocmask: + // case __NR_rt_sigqueueinfo: + case __NR_rt_sigreturn: + // case __NR_rt_sigsuspend: + // case __NR_rt_sigtimedwait: + // case __NR_rt_tgsigqueueinfo: + // case __NR_sigaltstack: + // case __NR_signalfd: + // case __NR_signalfd4: + return true; + default: + return false; + } +} + +bool IsOperationOnFd(int sysno) { + switch (sysno) { + case __NR_close: + case __NR_dup: + // case __NR_dup2: + // case __NR_dup3: + case __NR_fcntl: + case __NR_shutdown: + return true; + default: + return false; + } +} + +bool IsKernelInteralApi(int sysno) { + switch (sysno) { + case __NR_restart_syscall: + return true; + default: + return false; + } +} + +bool IsAllowedProcessStartOrDeath(int sysno) { + switch (sysno) { + case __NR_clone: // TODO(jln): restrict flags. + case __NR_exit: + case __NR_exit_group: + // case __NR_fork: + // case __NR_get_thread_area: + // case __NR_set_thread_area: + // case __NR_set_tid_address: + // case __NR_unshare: + // case __NR_vfork: + // case __NR_wait4: + // case __NR_waitid: + return true; + case __NR_setns: // Privileged. + default: + return false; + } +} + +bool IsAllowedEpoll(int sysno) { + switch (sysno) { + case __NR_epoll_create: + // case __NR_epoll_create1: + case __NR_epoll_ctl: + // case __NR_epoll_ctl_old: + // case __NR_epoll_pwait: + case __NR_epoll_wait: + // case __NR_epoll_wait_old: + return true; + default: + return false; + } +} + +bool IsAllowedGetOrModifySocket(int sysno) { + switch (sysno) { + case __NR_pipe: + // case __NR_pipe2: + case __NR_socketpair: // We will want to inspect its argument. + return true; + default: + case __NR_accept: + case __NR_accept4: + case __NR_bind: + case __NR_connect: + case __NR_socket: + case __NR_listen: + return false; + } +} + +bool IsNetworkSocketInformation(int sysno) { + switch (sysno) { + case __NR_getpeername: + case __NR_getsockname: + case __NR_getsockopt: + case __NR_setsockopt: + return true; + default: + return false; + } +} + +bool IsFutex(int sysno) { + switch (sysno) { + case __NR_futex: + // case __NR_get_robust_list: + case __NR_set_robust_list: + return true; + default: + return false; + } +} + +bool IsAllowedAddressSpaceAccess(int sysno) { + switch (sysno) { + case __NR_brk: case __NR_madvise: + // case __NR_mincore: + // case __NR_mlock: + // case __NR_mlockall: case __NR_mmap: + // case __NR_modify_ldt: case __NR_mprotect: + // case __NR_mremap: + // case __NR_msync: + // case __NR_munlock: + // case __NR_munlockall: case __NR_munmap: - case __NR_pipe: - case __NR_prctl: + // case __NR_readahead: + // case __NR_remap_file_pages: + return true; + default: + return false; + } +} + +bool IsAllowedGeneralIo(int sysno) { + switch (sysno) { + case __NR_lseek: + // case __NR_poll: + // case __NR_ppoll: + // case __NR_pread64: + // case __NR_preadv: + // case __NR_pselect6: + // case __NR_pwrite64: + // case __NR_pwritev: case __NR_read: - case __NR_recvmsg: - case __NR_restart_syscall: - case __NR_rt_sigaction: // Breakpad signal handler. - case __NR_rt_sigprocmask: - case __NR_rt_sigreturn: - case __NR_sched_yield: - case __NR_sendmsg: - case __NR_set_robust_list: - case __NR_shutdown: - case __NR_socketpair: + // case __NR_readv: + // case __NR_recvfrom: // Could specify source. + // case __NR_recvmmsg: // Could specify source. + case __NR_recvmsg: // Could specify source. + // case __NR_select: + // case __NR_sendfile: + // case __NR_sendmmsg: // Could specify destination. + case __NR_sendmsg: // Could specify destination. + // case __NR_sendto: // Could specify destination. + // case __NR_splice: + // case __NR_tee: + // case __NR_vmsplice: case __NR_write: + // case __NR_writev: return true; default: - if (IsGettimeSyscall(sysno) || - IsKillSyscall(sysno)) { - return true; - } else { - return false; - } + case __NR_ioctl: // Can be very powerful. + return false; + } +} + +bool IsAllowedPrctl(int sysno) { + switch (sysno) { + case __NR_prctl: + // case __NR_arch_prctl: + return true; + default: + return false; + } +} + +bool IsAllowedBasicScheduler(int sysno) { + switch (sysno) { + case __NR_sched_yield: + // case __NR_pause: + // case __NR_nanosleep: + // case __NR_getpriority: + return true; + case __NR_setpriority: + default: + return false; + } +} + +bool IsAdminOperation(int sysno) { + switch (sysno) { + case __NR_kexec_load: + case __NR_reboot: + case __NR_setdomainname: + case __NR_sethostname: + case __NR_syslog: + return true; + default: + return false; + } +} + +bool IsKernelModule(int sysno) { + switch (sysno) { + case __NR_create_module: + case __NR_delete_module: + case __NR_get_kernel_syms: // Should ENOSYS. + case __NR_init_module: + case __NR_query_module: + return true; + default: + return false; + } +} + +bool IsGlobalFSViewChange(int sysno) { + switch (sysno) { + case __NR_pivot_root: + case __NR_chroot: + case __NR_sync: + return true; + default: + return false; + } +} + +bool IsFsControl(int sysno) { + switch (sysno) { + case __NR_mount: + case __NR_nfsservctl: + case __NR_quotactl: + case __NR_swapoff: + case __NR_swapon: + case __NR_umount2: + return true; + default: + return false; + } +} + +bool IsNuma(int sysno) { + switch (sysno) { + case __NR_get_mempolicy: + case __NR_getcpu: + case __NR_mbind: + case __NR_migrate_pages: + case __NR_move_pages: + case __NR_set_mempolicy: + return true; + default: + return false; + } +} + +bool IsMessageQueue(int sysno) { + switch (sysno) { + case __NR_mq_getsetattr: + case __NR_mq_notify: + case __NR_mq_open: + case __NR_mq_timedreceive: + case __NR_mq_timedsend: + case __NR_mq_unlink: + return true; + default: + return false; + } +} + +bool IsGlobalProcessEnvironment(int sysno) { + switch (sysno) { + case __NR_acct: // Privileged. + case __NR_getrlimit: + case __NR_getrusage: + case __NR_personality: // Can change its personality as well. + case __NR_prlimit64: // Like setrlimit / getrlimit. + case __NR_setrlimit: + case __NR_times: + return true; + default: + return false; + } +} + +bool IsDebug(int sysno) { + switch (sysno) { + case __NR_ptrace: + case __NR_process_vm_readv: + case __NR_process_vm_writev: + case __NR_kcmp: + return true; + default: + return false; + } +} + +bool IsGlobalSystemStatus(int sysno) { + switch (sysno) { + case __NR__sysctl: + case __NR_sysfs: + case __NR_sysinfo: + case __NR_uname: + return true; + default: + return false; + } +} + +bool IsEventFd(int sysno) { + switch (sysno) { + case __NR_eventfd: + // case __NR_eventfd2: + return true; + default: + return false; + } +} + +// Asynchronous I/O API. +bool IsAsyncIo(int sysno) { + switch (sysno) { + case __NR_io_cancel: + case __NR_io_destroy: + case __NR_io_getevents: + case __NR_io_setup: + case __NR_io_submit: + return true; + default: + return false; + } +} + +bool IsKeyManagement(int sysno) { + switch (sysno) { + case __NR_add_key: + case __NR_keyctl: + case __NR_request_key: + return true; + default: + return false; + } +} + +bool IsSystemVSemaphores(int sysno) { + switch (sysno) { + case __NR_semctl: + case __NR_semget: + case __NR_semop: + case __NR_semtimedop: + return true; + default: + return false; + } +} + +// These give a lot of ambient authority and bypass the setuid sandbox. +bool IsSystemVSharedMemory(int sysno) { + switch (sysno) { + case __NR_shmat: + case __NR_shmctl: + case __NR_shmdt: + // case __NR_shmget: + return true; + default: + return false; + } +} + +bool IsSystemVMessageQueue(int sysno) { + switch (sysno) { + case __NR_msgctl: + case __NR_msgget: + case __NR_msgrcv: + case __NR_msgsnd: + return true; + default: + return false; + } +} + +bool IsAdvancedScheduler(int sysno) { + switch (sysno) { + case __NR_ioprio_get: // IO scheduler. + case __NR_ioprio_set: + case __NR_sched_get_priority_max: + case __NR_sched_get_priority_min: + case __NR_sched_getaffinity: + case __NR_sched_getparam: + case __NR_sched_getscheduler: + case __NR_sched_rr_get_interval: + case __NR_sched_setaffinity: + case __NR_sched_setparam: + case __NR_sched_setscheduler: + return true; + default: + return false; + } +} + +bool IsInotify(int sysno) { + switch (sysno) { + case __NR_inotify_add_watch: + case __NR_inotify_init: + case __NR_inotify_init1: + case __NR_inotify_rm_watch: + return true; + default: + return false; + } +} + +bool IsFaNotify(int sysno) { + switch (sysno) { + case __NR_fanotify_init: + case __NR_fanotify_mark: + return true; + default: + return false; + } +} + +bool IsTimer(int sysno) { + switch (sysno) { + case __NR_getitimer: + case __NR_alarm: + case __NR_setitimer: + return true; + default: + return false; + } +} + +bool IsAdvancedTimer(int sysno) { + switch (sysno) { + case __NR_timer_create: + case __NR_timer_delete: + case __NR_timer_getoverrun: + case __NR_timer_gettime: + case __NR_timer_settime: + case __NR_timerfd_create: + case __NR_timerfd_gettime: + case __NR_timerfd_settime: + return true; + default: + return false; + } +} + +bool IsExtendedAttributes(int sysno) { + switch (sysno) { + case __NR_fgetxattr: + case __NR_flistxattr: + case __NR_fremovexattr: + case __NR_fsetxattr: + case __NR_getxattr: + case __NR_lgetxattr: + case __NR_listxattr: + case __NR_llistxattr: + case __NR_lremovexattr: + case __NR_lsetxattr: + case __NR_removexattr: + case __NR_setxattr: + return true; + default: + return false; + } +} + +// Various system calls that need to be researched. +// TODO(jln): classify this better. +bool IsMiscSyscall(int sysno) { + switch (sysno) { + case __NR_name_to_handle_at: + case __NR_open_by_handle_at: + case __NR_perf_event_open: + case __NR_syncfs: + case __NR_vhangup: + // The system calls below are not implemented. + case __NR_afs_syscall: + case __NR_getpmsg: + case __NR_putpmsg: + case __NR_security: + case __NR_tuxcall: + case __NR_vserver: + return true; + default: + return false; + } +} + +// End of the system call sets section. + +// x86_64 only because it references system calls that are multiplexed on IA32. +bool IsGpuAndFlashPolicyAllowed_x86_64(int sysno) { + if (IsAllowedAddressSpaceAccess(sysno) || + IsAllowedBasicScheduler(sysno) || + IsAllowedEpoll(sysno) || + IsAllowedFileSystemCapabilitySyscall(sysno) || + IsAllowedGeneralIo(sysno) || + IsAllowedGetOrModifySocket(sysno) || + IsAllowedGettimeSyscall(sysno) || + IsAllowedPrctl(sysno) || + IsAllowedProcessStartOrDeath(sysno) || + IsAllowedSignalHandling(sysno) || + IsFutex(sysno) || + IsGetProcessIdSyscall(sysno) || + IsKernelInteralApi(sysno) || + IsKillSyscall(sysno) || + IsOperationOnFd(sysno)) { + return true; + } else { + return false; + } +} + +// System calls that will trigger the crashing sigsys handler. +bool IsGpuAndFlashPolicyWatched_x86_64(int sysno) { + if (IsAdminOperation(sysno) || + IsAdvancedScheduler(sysno) || + IsAdvancedTimer(sysno) || + IsAsyncIo(sysno) || + IsDebug(sysno) || + IsEventFd(sysno) || + IsExtendedAttributes(sysno) || + IsFaNotify(sysno) || + IsFsControl(sysno) || + IsGlobalFSViewChange(sysno) || + IsGlobalProcessEnvironment(sysno) || + IsGlobalSystemStatus(sysno) || + IsInotify(sysno) || + IsKernelModule(sysno) || + IsKeyManagement(sysno) || + IsMessageQueue(sysno) || + IsMiscSyscall(sysno) || + IsNetworkSocketInformation(sysno) || + IsNuma(sysno) || + IsProcessGroupOrSession(sysno) || + IsProcessPrivilegeChange(sysno) || + IsSystemVMessageQueue(sysno) || + IsSystemVSemaphores(sysno) || + IsSystemVSharedMemory(sysno) || + IsTimer(sysno)) { + return true; + } else { + return false; } } // x86_64 only because it references system calls that are multiplexed on IA32. playground2::Sandbox::ErrorCode GpuProcessPolicy_x86_64(int sysno) { switch(sysno) { - case __NR_eventfd2: case __NR_getpid: // Nvidia binary driver. case __NR_getppid: // ATI binary driver. case __NR_ioctl: @@ -287,14 +902,20 @@ playground2::Sandbox::ErrorCode GpuProcessPolicy_x86_64(int sysno) { return playground2::Sandbox::ErrorCode(GpuOpenSIGSYS_Handler, NULL); } default: - if (IsGpuAndFlashPolicyAllowed_x86_64(sysno)) { + if (IsGpuAndFlashPolicyAllowed_x86_64(sysno) || IsEventFd(sysno)) { return playground2::Sandbox::SB_ALLOWED; } // Generally, filename-based syscalls will fail with ENOENT to behave // similarly to a possible future setuid sandbox. - if (IsFileSystemSyscall(sysno)) { + if (IsFileSystemSyscall(sysno) || IsAmbientFileSystemSyscall(sysno)) { return ENOENT; } + + if (IsGpuAndFlashPolicyWatched_x86_64(sysno)) { + // Previously unseen syscalls. TODO(jln): some of these should + // be denied gracefully right away. + return playground2::Sandbox::ErrorCode(CrashSIGSYS_Handler, NULL); + } // In any other case crash the program with our SIGSYS handler return playground2::Sandbox::ErrorCode(CrashSIGSYS_Handler, NULL); } @@ -306,9 +927,6 @@ playground2::Sandbox::ErrorCode FlashProcessPolicy_x86_64(int sysno) { case __NR_sched_getaffinity: case __NR_sched_setscheduler: // These are under investigation, and hopefully not here for the long term. - case __NR_shmat: - case __NR_shmctl: - case __NR_shmdt: case __NR_times: case __NR_wait4: return playground2::Sandbox::SB_ALLOWED; @@ -317,12 +935,18 @@ playground2::Sandbox::ErrorCode FlashProcessPolicy_x86_64(int sysno) { case __NR_socket: return EACCES; default: - if (IsGpuAndFlashPolicyAllowed_x86_64(sysno)) { + if (IsGpuAndFlashPolicyAllowed_x86_64(sysno) || + IsSystemVSharedMemory(sysno)) { return playground2::Sandbox::SB_ALLOWED; } - if (IsFileSystemSyscall(sysno)) { + if (IsFileSystemSyscall(sysno) || IsAmbientFileSystemSyscall(sysno)) { return ENOENT; } + if (IsGpuAndFlashPolicyWatched_x86_64(sysno)) { + // Previously unseen syscalls. TODO(jln): some of these should + // be denied gracefully right away. + return playground2::Sandbox::ErrorCode(CrashSIGSYS_Handler, NULL); + } // In any other case crash the program with our SIGSYS handler. return playground2::Sandbox::ErrorCode(CrashSIGSYS_Handler, NULL); } |