virtual ResultExpr ClonePolicy() const { // Allow use for simple thread creation (pthread_create) only. // WARNING: s390 and cris pass the flags in the second arg -- see // CLONE_BACKWARDS2 in arch/Kconfig in the kernel source -- but we // don't support seccomp-bpf on those archs yet. Arg<int> flags(0); // The glibc source hasn't changed the thread creation clone flags // since 2004, so this *should* be safe to hard-code. Bionic's // value has changed a few times, and has converged on the same one // as glibc; allow any of them. static const int flags_common = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM; static const int flags_modern = flags_common | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID; // Can't use CASES here because its decltype magic infers const // int instead of regular int and bizarre voluminous errors issue // forth from the depths of the standard library implementation. return Switch(flags) #ifdef ANDROID .Case(flags_common | CLONE_DETACHED, Allow()) // <= JB 4.2 .Case(flags_common, Allow()) // JB 4.3 or KK 4.4 #endif .Case(flags_modern, Allow()) // Android L or glibc .Default(InvalidSyscall()); }
virtual ResultExpr PrctlPolicy() const { // Note: this will probably need PR_SET_VMA if/when it's used on // Android without being overridden by an allow-all policy, and // the constant will need to be defined locally. Arg<int> op(0); return Switch(op) .CASES((PR_GET_SECCOMP, // BroadcastSetThreadSandbox, etc. PR_SET_NAME, // Thread creation PR_SET_DUMPABLE), // Crash reporting Allow()) .Default(InvalidSyscall()); }
virtual ResultExpr EvaluateSyscall(int sysno) const override { switch (sysno) { // Simulate opening the plugin file. #ifdef __NR_open case __NR_open: #endif case __NR_openat: return Trap(OpenTrap, mPlugin); // ipc::Shmem case __NR_mprotect: return Allow(); case __NR_madvise: { Arg<int> advice(2); return If(advice == MADV_DONTNEED, Allow()) .Else(InvalidSyscall()); } default: return SandboxPolicyCommon::EvaluateSyscall(sysno); } }
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(domain == AF_UNIX && (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_SETSOCKOPT: case SYS_GETSOCKNAME: case SYS_GETPEERNAME: case SYS_SHUTDOWN: return Some(Allow()); #endif default: return SandboxPolicyCommon::EvaluateSocketCall(aCall); } }
virtual ResultExpr EvaluateSyscall(int sysno) const override { switch (sysno) { // Timekeeping case __NR_clock_gettime: { Arg<clockid_t> clk_id(0); return If(clk_id == CLOCK_MONOTONIC, Allow()) .ElseIf(clk_id == CLOCK_REALTIME, Allow()) .Else(InvalidSyscall()); } case __NR_gettimeofday: #ifdef __NR_time case __NR_time: #endif case __NR_nanosleep: return Allow(); // Thread synchronization case __NR_futex: // FIXME: This could be more restrictive.... return Allow(); // Asynchronous I/O case __NR_epoll_wait: case __NR_epoll_pwait: case __NR_epoll_ctl: case __NR_ppoll: case __NR_poll: return Allow(); // Used when requesting a crash dump. case __NR_pipe: return Allow(); // Metadata of opened files CASES_FOR_fstat: return Allow(); // Simple I/O case __NR_write: case __NR_read: case __NR_writev: // see SandboxLogging.cpp return Allow(); // Memory mapping CASES_FOR_mmap: case __NR_munmap: return Allow(); // Signal handling #if defined(ANDROID) || defined(MOZ_ASAN) case __NR_sigaltstack: #endif CASES_FOR_sigreturn: CASES_FOR_sigprocmask: CASES_FOR_sigaction: return Allow(); // Send signals within the process (raise(), profiling, etc.) case __NR_tgkill: { Arg<pid_t> tgid(0); return If(tgid == getpid(), Allow()) .Else(InvalidSyscall()); } #if defined(ANDROID) && ANDROID_VERSION < 16 // Polyfill with tgkill; see above. case __NR_tkill: return Trap(TKillCompatTrap, nullptr); #endif // Yield case __NR_sched_yield: return Allow(); // Thread creation. case __NR_clone: return ClonePolicy(); // More thread creation. #ifdef __NR_set_robust_list case __NR_set_robust_list: return Allow(); #endif #ifdef ANDROID case __NR_set_tid_address: return Allow(); #endif // prctl case __NR_prctl: return PrctlPolicy(); // NSPR can call this when creating a thread, but it will accept a // polite "no". case __NR_getpriority: // But if thread creation races with sandbox startup, that call // could succeed, and then we get one of these: case __NR_setpriority: return Error(EACCES); // Stack bounds are obtained via pthread_getattr_np, which calls // this but doesn't actually need it: case __NR_sched_getaffinity: return Error(ENOSYS); // Read own pid/tid. case __NR_getpid: case __NR_gettid: return Allow(); // Discard capabilities case __NR_close: return Allow(); // Machine-dependent stuff #ifdef __arm__ case __ARM_NR_breakpoint: case __ARM_NR_cacheflush: case __ARM_NR_usr26: // FIXME: do we actually need this? case __ARM_NR_usr32: case __ARM_NR_set_tls: return Allow(); #endif // Needed when being debugged: case __NR_restart_syscall: return Allow(); // Terminate threads or the process case __NR_exit: case __NR_exit_group: return Allow(); #ifdef MOZ_ASAN // ASAN's error reporter wants to know if stderr is a tty. case __NR_ioctl: { Arg<int> fd(0); return If(fd == STDERR_FILENO, Allow()) .Else(InvalidSyscall()); } // ...and before compiler-rt r209773, it will call readlink on // /proc/self/exe and use the cached value only if that fails: case __NR_readlink: case __NR_readlinkat: return Error(ENOENT); // ...and if it found an external symbolizer, it will try to run it: // (See also bug 1081242 comment #7.) CASES_FOR_stat: return Error(ENOENT); #endif default: return SandboxPolicyBase::EvaluateSyscall(sysno); } }
sandbox::bpf_dsl::ResultExpr SandboxPolicyBase::EvaluateSyscall(int aSysno) const { switch (aSysno) { #ifdef __NR_socketcall case __NR_socketcall: { Arg<int> call(0); UniquePtr<Caser<int>> acc(new Caser<int>(Switch(call))); for (int i = SYS_SOCKET; i <= SYS_SENDMMSG; ++i) { auto thisCase = EvaluateSocketCall(i); // Optimize out cases that are equal to the default. if (thisCase) { acc.reset(new Caser<int>(acc->Case(i, *thisCase))); } } return acc->Default(InvalidSyscall()); } #ifndef ANDROID case __NR_ipc: { Arg<int> callAndVersion(0); auto call = callAndVersion & 0xFFFF; UniquePtr<Caser<int>> acc(new Caser<int>(Switch(call))); for (int i = SEMOP; i <= DIPC; ++i) { auto thisCase = EvaluateIpcCall(i); // Optimize out cases that are equal to the default. if (thisCase) { acc.reset(new Caser<int>(acc->Case(i, *thisCase))); } } return acc->Default(InvalidSyscall()); } #endif // ANDROID #else // __NR_socketcall #define DISPATCH_SOCKETCALL(sysnum, socketnum) \ case sysnum: \ return EvaluateSocketCall(socketnum).valueOr(InvalidSyscall()) DISPATCH_SOCKETCALL(__NR_socket, SYS_SOCKET); DISPATCH_SOCKETCALL(__NR_bind, SYS_BIND); DISPATCH_SOCKETCALL(__NR_connect, SYS_CONNECT); DISPATCH_SOCKETCALL(__NR_listen, SYS_LISTEN); DISPATCH_SOCKETCALL(__NR_accept, SYS_ACCEPT); DISPATCH_SOCKETCALL(__NR_getsockname, SYS_GETSOCKNAME); DISPATCH_SOCKETCALL(__NR_getpeername, SYS_GETPEERNAME); DISPATCH_SOCKETCALL(__NR_socketpair, SYS_SOCKETPAIR); #ifdef __NR_send DISPATCH_SOCKETCALL(__NR_send, SYS_SEND); DISPATCH_SOCKETCALL(__NR_recv, SYS_RECV); #endif // __NR_send DISPATCH_SOCKETCALL(__NR_sendto, SYS_SENDTO); DISPATCH_SOCKETCALL(__NR_recvfrom, SYS_RECVFROM); DISPATCH_SOCKETCALL(__NR_shutdown, SYS_SHUTDOWN); DISPATCH_SOCKETCALL(__NR_setsockopt, SYS_SETSOCKOPT); DISPATCH_SOCKETCALL(__NR_getsockopt, SYS_GETSOCKOPT); DISPATCH_SOCKETCALL(__NR_sendmsg, SYS_SENDMSG); DISPATCH_SOCKETCALL(__NR_recvmsg, SYS_RECVMSG); DISPATCH_SOCKETCALL(__NR_accept4, SYS_ACCEPT4); DISPATCH_SOCKETCALL(__NR_recvmmsg, SYS_RECVMMSG); DISPATCH_SOCKETCALL(__NR_sendmmsg, SYS_SENDMMSG); #undef DISPATCH_SOCKETCALL #ifndef ANDROID #define DISPATCH_SYSVCALL(sysnum, ipcnum) \ case sysnum: \ return EvaluateIpcCall(ipcnum).valueOr(InvalidSyscall()) DISPATCH_SYSVCALL(__NR_semop, SEMOP); DISPATCH_SYSVCALL(__NR_semget, SEMGET); DISPATCH_SYSVCALL(__NR_semctl, SEMCTL); DISPATCH_SYSVCALL(__NR_semtimedop, SEMTIMEDOP); DISPATCH_SYSVCALL(__NR_msgsnd, MSGSND); DISPATCH_SYSVCALL(__NR_msgrcv, MSGRCV); DISPATCH_SYSVCALL(__NR_msgget, MSGGET); DISPATCH_SYSVCALL(__NR_msgctl, MSGCTL); DISPATCH_SYSVCALL(__NR_shmat, SHMAT); DISPATCH_SYSVCALL(__NR_shmdt, SHMDT); DISPATCH_SYSVCALL(__NR_shmget, SHMGET); DISPATCH_SYSVCALL(__NR_shmctl, SHMCTL); #undef DISPATCH_SYSVCALL #endif // ANDROID #endif // __NR_socketcall default: return InvalidSyscall(); } }