diff options
Diffstat (limited to 'security/sandbox/linux/SandboxFilter.cpp')
-rw-r--r-- | security/sandbox/linux/SandboxFilter.cpp | 489 |
1 files changed, 0 insertions, 489 deletions
diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp index f8db9dc80..da7e54300 100644 --- a/security/sandbox/linux/SandboxFilter.cpp +++ b/security/sandbox/linux/SandboxFilter.cpp @@ -340,495 +340,6 @@ public: // The process-type-specific syscall rules start here: -#ifdef MOZ_CONTENT_SANDBOX -// The seccomp-bpf filter for content processes is not a true sandbox -// on its own; its purpose is attack surface reduction and syscall -// interception in support of a semantic sandboxing layer. On B2G -// this is the Android process permission model; on desktop, -// namespaces and chroot() will be used. -class ContentSandboxPolicy : public SandboxPolicyCommon { - SandboxBrokerClient* mBroker; - - // Trap handlers for filesystem brokering. - // (The amount of code duplication here could be improved....) -#ifdef __NR_open - static intptr_t OpenTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto flags = static_cast<int>(aArgs.args[1]); - return broker->Open(path, flags); - } -#endif - - static intptr_t OpenAtTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto fd = static_cast<int>(aArgs.args[0]); - auto path = reinterpret_cast<const char*>(aArgs.args[1]); - auto flags = static_cast<int>(aArgs.args[2]); - if (fd != AT_FDCWD && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative openat(%d, \"%s\", 0%o)", - fd, path, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - return broker->Open(path, flags); - } - -#ifdef __NR_access - static intptr_t AccessTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto mode = static_cast<int>(aArgs.args[1]); - return broker->Access(path, mode); - } -#endif - - static intptr_t AccessAtTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto fd = static_cast<int>(aArgs.args[0]); - auto path = reinterpret_cast<const char*>(aArgs.args[1]); - auto mode = static_cast<int>(aArgs.args[2]); - // Linux's faccessat syscall has no "flags" argument. Attempting - // to handle the flags != 0 case is left to userspace; this is - // impossible to do correctly in all cases, but that's not our - // problem. - if (fd != AT_FDCWD && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative faccessat(%d, \"%s\", %d)", - fd, path, mode); - return BlockedSyscallTrap(aArgs, nullptr); - } - return broker->Access(path, mode); - } - - static intptr_t StatTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]); - return broker->Stat(path, buf); - } - - static intptr_t LStatTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]); - return broker->LStat(path, buf); - } - - static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto fd = static_cast<int>(aArgs.args[0]); - auto path = reinterpret_cast<const char*>(aArgs.args[1]); - auto buf = reinterpret_cast<statstruct*>(aArgs.args[2]); - auto flags = static_cast<int>(aArgs.args[3]); - if (fd != AT_FDCWD && path[0] != '/') { - SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)", - fd, path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) { - SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)", - (flags & ~AT_SYMLINK_NOFOLLOW), fd, path, buf, flags); - return BlockedSyscallTrap(aArgs, nullptr); - } - return (flags & AT_SYMLINK_NOFOLLOW) == 0 - ? broker->Stat(path, buf) - : broker->LStat(path, buf); - } - - static intptr_t ChmodTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto mode = static_cast<mode_t>(aArgs.args[1]); - return broker->Chmod(path, mode); - } - - static intptr_t LinkTrap(ArgsRef aArgs, void *aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto path2 = reinterpret_cast<const char*>(aArgs.args[1]); - return broker->Link(path, path2); - } - - static intptr_t SymlinkTrap(ArgsRef aArgs, void *aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto path2 = reinterpret_cast<const char*>(aArgs.args[1]); - return broker->Symlink(path, path2); - } - - static intptr_t RenameTrap(ArgsRef aArgs, void *aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto path2 = reinterpret_cast<const char*>(aArgs.args[1]); - return broker->Rename(path, path2); - } - - static intptr_t MkdirTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto mode = static_cast<mode_t>(aArgs.args[1]); - return broker->Mkdir(path, mode); - } - - static intptr_t RmdirTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - return broker->Rmdir(path); - } - - static intptr_t UnlinkTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - return broker->Unlink(path); - } - - static intptr_t ReadlinkTrap(ArgsRef aArgs, void* aux) { - auto broker = static_cast<SandboxBrokerClient*>(aux); - auto path = reinterpret_cast<const char*>(aArgs.args[0]); - auto buf = reinterpret_cast<char*>(aArgs.args[1]); - auto size = static_cast<size_t>(aArgs.args[2]); - return broker->Readlink(path, buf, size); - } - - static intptr_t GetPPidTrap(ArgsRef aArgs, void* aux) { - // In a pid namespace, getppid() will return 0. We will return 0 instead - // of the real parent pid to see what breaks when we introduce the - // pid namespace (Bug 1151624). - return 0; - } - -public: - explicit ContentSandboxPolicy(SandboxBrokerClient* aBroker):mBroker(aBroker) { } - virtual ~ContentSandboxPolicy() { } - virtual ResultExpr PrctlPolicy() const override { - // Ideally this should be restricted to a whitelist, but content - // uses enough things that it's not trivial to determine it. - return Allow(); - } - virtual Maybe<ResultExpr> EvaluateSocketCall(int aCall) const override { - switch(aCall) { - case SYS_RECVFROM: - case SYS_SENDTO: - return Some(Allow()); - - case SYS_SOCKETPAIR: { - // See bug 1066750. - if (!kSocketCallHasArgs) { - // We can't filter the args if the platform passes them by pointer. - return Some(Allow()); - } - Arg<int> domain(0), type(1); - return Some(If(AllOf(domain == AF_UNIX, - AnyOf(type == SOCK_STREAM, type == SOCK_SEQPACKET)), - Allow()) - .Else(InvalidSyscall())); - } - -#ifdef ANDROID - case SYS_SOCKET: - return Some(Error(EACCES)); -#else // #ifdef DESKTOP - case SYS_RECV: - case SYS_SEND: - case SYS_SOCKET: // DANGEROUS - case SYS_CONNECT: // DANGEROUS - case SYS_ACCEPT: - case SYS_ACCEPT4: - case SYS_BIND: - case SYS_LISTEN: - case SYS_GETSOCKOPT: - case SYS_SETSOCKOPT: - case SYS_GETSOCKNAME: - case SYS_GETPEERNAME: - case SYS_SHUTDOWN: - return Some(Allow()); -#endif - default: - return SandboxPolicyCommon::EvaluateSocketCall(aCall); - } - } - -#ifdef DESKTOP - virtual Maybe<ResultExpr> EvaluateIpcCall(int aCall) const override { - switch(aCall) { - // These are a problem: SysV shared memory follows the Unix - // "same uid policy" and can't be restricted/brokered like file - // access. But the graphics layer might not be using them - // anymore; this needs to be studied. - case SHMGET: - case SHMCTL: - case SHMAT: - case SHMDT: - case SEMGET: - case SEMCTL: - case SEMOP: - case MSGGET: - return Some(Allow()); - default: - return SandboxPolicyCommon::EvaluateIpcCall(aCall); - } - } -#endif - - virtual ResultExpr EvaluateSyscall(int sysno) const override { - if (mBroker) { - // Have broker; route the appropriate syscalls to it. - switch (sysno) { - case __NR_open: - return Trap(OpenTrap, mBroker); - case __NR_openat: - return Trap(OpenAtTrap, mBroker); - case __NR_access: - return Trap(AccessTrap, mBroker); - case __NR_faccessat: - return Trap(AccessAtTrap, mBroker); - CASES_FOR_stat: - return Trap(StatTrap, mBroker); - CASES_FOR_lstat: - return Trap(LStatTrap, mBroker); - CASES_FOR_fstatat: - return Trap(StatAtTrap, mBroker); - case __NR_chmod: - return Trap(ChmodTrap, mBroker); - case __NR_link: - return Trap(LinkTrap, mBroker); - case __NR_mkdir: - return Trap(MkdirTrap, mBroker); - case __NR_symlink: - return Trap(SymlinkTrap, mBroker); - case __NR_rename: - return Trap(RenameTrap, mBroker); - case __NR_rmdir: - return Trap(RmdirTrap, mBroker); - case __NR_unlink: - return Trap(UnlinkTrap, mBroker); - case __NR_readlink: - return Trap(ReadlinkTrap, mBroker); - } - } else { - // No broker; allow the syscalls directly. )-: - switch(sysno) { - case __NR_open: - case __NR_openat: - case __NR_access: - case __NR_faccessat: - CASES_FOR_stat: - CASES_FOR_lstat: - CASES_FOR_fstatat: - case __NR_chmod: - case __NR_link: - case __NR_mkdir: - case __NR_symlink: - case __NR_rename: - case __NR_rmdir: - case __NR_unlink: - case __NR_readlink: - return Allow(); - } - } - - switch (sysno) { -#ifdef DESKTOP - case __NR_getppid: - return Trap(GetPPidTrap, nullptr); - - // Filesystem syscalls that need more work to determine who's - // using them, if they need to be, and what we intend to about it. - case __NR_getcwd: - CASES_FOR_statfs: - CASES_FOR_fstatfs: - case __NR_quotactl: - CASES_FOR_fchown: - case __NR_fchmod: - case __NR_flock: -#endif - return Allow(); - - case __NR_readlinkat: -#ifdef DESKTOP - // Bug 1290896 - return Allow(); -#else - // Workaround for bug 964455: - return Error(EINVAL); -#endif - - CASES_FOR_select: - case __NR_pselect6: - return Allow(); - - CASES_FOR_getdents: - CASES_FOR_ftruncate: - case __NR_writev: - case __NR_pread64: -#ifdef DESKTOP - case __NR_pwrite64: - case __NR_readahead: -#endif - return Allow(); - - case __NR_ioctl: - // ioctl() is for GL. Remove when GL proxy is implemented. - // Additionally ioctl() might be a place where we want to have - // argument filtering - return Allow(); - - CASES_FOR_fcntl: - // Some fcntls have significant side effects like sending - // arbitrary signals, and there's probably nontrivial kernel - // attack surface; this should be locked down more if possible. - return Allow(); - - case __NR_mprotect: - case __NR_brk: - case __NR_madvise: -#if !defined(MOZ_MEMORY) - // libc's realloc uses mremap (Bug 1286119). - case __NR_mremap: -#endif - return Allow(); - - case __NR_sigaltstack: - return Allow(); - -#ifdef __NR_set_thread_area - case __NR_set_thread_area: - return Allow(); -#endif - - case __NR_getrusage: - case __NR_times: - return Allow(); - - case __NR_dup: - return Allow(); - - CASES_FOR_getuid: - CASES_FOR_getgid: - CASES_FOR_geteuid: - CASES_FOR_getegid: - return Allow(); - - case __NR_fsync: - case __NR_msync: - return Allow(); - - case __NR_getpriority: - case __NR_setpriority: - case __NR_sched_get_priority_min: - case __NR_sched_get_priority_max: - case __NR_sched_getscheduler: - case __NR_sched_setscheduler: - case __NR_sched_getparam: - case __NR_sched_setparam: -#ifdef DESKTOP - case __NR_sched_getaffinity: -#endif - return Allow(); - -#ifdef DESKTOP - case __NR_pipe2: - return Allow(); - - CASES_FOR_getrlimit: - case __NR_clock_getres: - CASES_FOR_getresuid: - CASES_FOR_getresgid: - return Allow(); - - case __NR_umask: - case __NR_kill: - case __NR_wait4: -#ifdef __NR_waitpid - case __NR_waitpid: -#endif -#ifdef __NR_arch_prctl - case __NR_arch_prctl: -#endif - return Allow(); - - case __NR_eventfd2: - case __NR_inotify_init1: - case __NR_inotify_add_watch: - case __NR_inotify_rm_watch: - return Allow(); - -#ifdef __NR_memfd_create - case __NR_memfd_create: - return Allow(); -#endif - -#ifdef __NR_rt_tgsigqueueinfo - // Only allow to send signals within the process. - case __NR_rt_tgsigqueueinfo: { - Arg<pid_t> tgid(0); - return If(tgid == getpid(), Allow()) - .Else(InvalidSyscall()); - } -#endif - - case __NR_mlock: - case __NR_munlock: - return Allow(); - - // We can't usefully allow fork+exec, even on a temporary basis; - // the child would inherit the seccomp-bpf policy and almost - // certainly die from an unexpected SIGSYS. We also can't have - // fork() crash, currently, because there are too many system - // libraries/plugins that try to run commands. But they can - // usually do something reasonable on error. - case __NR_clone: - return ClonePolicy(Error(EPERM)); - -#ifdef __NR_fadvise64 - case __NR_fadvise64: - return Allow(); -#endif - -#ifdef __NR_fadvise64_64 - case __NR_fadvise64_64: - return Allow(); -#endif - - case __NR_fallocate: - return Allow(); - - case __NR_get_mempolicy: - return Allow(); - -#endif // DESKTOP - -#ifdef __NR_getrandom - case __NR_getrandom: - return Allow(); -#endif - - // nsSystemInfo uses uname (and we cache an instance, so - // the info remains present even if we block the syscall) - case __NR_uname: -#ifdef DESKTOP - case __NR_sysinfo: -#endif - return Allow(); - -#ifdef MOZ_JPROF - case __NR_setitimer: - return Allow(); -#endif // MOZ_JPROF - - default: - return SandboxPolicyCommon::EvaluateSyscall(sysno); - } - } -}; - -UniquePtr<sandbox::bpf_dsl::Policy> -GetContentSandboxPolicy(SandboxBrokerClient* aMaybeBroker) -{ - return UniquePtr<sandbox::bpf_dsl::Policy>(new ContentSandboxPolicy(aMaybeBroker)); -} -#endif // MOZ_CONTENT_SANDBOX - - #ifdef MOZ_GMP_SANDBOX // Unlike for content, the GeckoMediaPlugin seccomp-bpf policy needs // to be an effective sandbox by itself, because we allow GMP on Linux |