From d49a019f05d0daead9859dbf21a9f159a8d13e54 Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Fri, 14 Jul 2017 16:21:21 +0800 Subject: [PATCH] Add support for using seccomp_bpf on mips64el. Currently, seccomp_bpf is not supported on mips64el, and the build configuration sets use_seccomp_bpf=false on mips64el. This CL adds support for seccomp-bpf on mips64el, and resolves many compiler errors when compiling on mips64el. This patch merge into chromium master branch: https://chromium.googlesource.com/chromium/src/+/534d7ce2af699715acfc4fe516ef3c2ffee65bc5 BUG: 742738 R= machenbach@chromium.org, brettw@chromium.org --- base/macros.h | 10 +++ .../sandbox_linux/sandbox_seccomp_bpf_linux.cc | 4 +- sandbox/features.gni | 5 +- sandbox/linux/BUILD.gn | 1 + sandbox/linux/bpf_dsl/linux_syscall_ranges.h | 9 ++- sandbox/linux/bpf_dsl/seccomp_macros.h | 63 +++++++++++++++- sandbox/linux/bpf_dsl/syscall_set.cc | 5 +- .../linux/seccomp-bpf-helpers/baseline_policy.cc | 8 +- .../linux/seccomp-bpf-helpers/sigsys_handlers.cc | 2 +- sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc | 88 ++++++++++++---------- sandbox/linux/seccomp-bpf-helpers/syscall_sets.h | 13 ++-- sandbox/linux/seccomp-bpf/syscall.cc | 51 ++++++++++++- sandbox/linux/system_headers/linux_seccomp.h | 3 + sandbox/linux/system_headers/linux_signal.h | 9 ++- sandbox/linux/system_headers/linux_syscalls.h | 4 +- sandbox/linux/system_headers/linux_ucontext.h | 4 +- .../linux/system_headers/mips64_linux_syscalls.h | 2 +- .../linux/system_headers/mips64_linux_ucontext.h | 50 ++++++++++++ sandbox/linux/system_headers/mips_linux_syscalls.h | 2 +- 20 files changed, 267 insertions(+), 67 deletions(-) create mode 100644 sandbox/linux/system_headers/mips64_linux_ucontext.h diff --git a/base/macros.h b/base/macros.h index 154d4b0..d88119a 100644 --- a/base/macros.h +++ b/base/macros.h @@ -12,6 +12,16 @@ #include // For size_t. +// Distinguish mips32. +#if defined(__mips__) && (_MIPS_SIM == _ABIO32) +#define __mips32__ +#endif + +// Distinguish mips64. +#if defined(__mips__) && (_MIPS_SIM == _ABI64) +#define __mips64__ +#endif + // Put this in the declarations for a class to be uncopyable. #define DISALLOW_COPY(TypeName) \ TypeName(const TypeName&) = delete diff --git a/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc b/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc index 9b27f94..1ab05a7 100644 --- a/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc +++ b/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc @@ -47,9 +47,9 @@ using sandbox::bpf_dsl::ResultExpr; // Make sure that seccomp-bpf does not get disabled by mistake. Also make sure // that we think twice about this when adding a new architecture. -#if !defined(ARCH_CPU_ARM64) +#if !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_MIPS64EL) #error "Seccomp-bpf disabled on supported architecture!" -#endif // !defined(ARCH_CPU_ARM64) +#endif // !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_MIPS64EL) #endif // diff --git a/sandbox/features.gni b/sandbox/features.gni index aa18c04..89693c5 100644 --- a/sandbox/features.gni +++ b/sandbox/features.gni @@ -4,13 +4,14 @@ import("//build/config/nacl/config.gni") -# The seccomp-bpf sandbox is only supported on five architectures +# The seccomp-bpf sandbox is only supported on six architectures # currently. # Do not disable seccomp_bpf anywhere without talking to # security@chromium.org! use_seccomp_bpf = (is_linux || is_android) && (current_cpu == "x86" || current_cpu == "x64" || current_cpu == "arm" || - current_cpu == "arm64" || current_cpu == "mipsel") + current_cpu == "arm64" || current_cpu == "mipsel" || + current_cpu == "mips64el") use_seccomp_bpf = use_seccomp_bpf || is_nacl_nonsfi diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index 421d8b0..4b321e2 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn @@ -431,6 +431,7 @@ source_set("sandbox_services_headers") { "system_headers/linux_time.h", "system_headers/linux_ucontext.h", "system_headers/mips64_linux_syscalls.h", + "system_headers/mips64_linux_ucontext.h", "system_headers/mips_linux_syscalls.h", "system_headers/mips_linux_ucontext.h", "system_headers/x86_32_linux_syscalls.h", diff --git a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h index a747770..334a00b 100644 --- a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h +++ b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h @@ -33,16 +33,19 @@ #define MIN_GHOST_SYSCALL (MIN_PRIVATE_SYSCALL + 0xfff0u) #define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u) -#elif defined(__mips__) && (_MIPS_SIM == _ABIO32) +#elif defined(__mips32__) #include // for __NR_O32_Linux and __NR_Linux_syscalls #define MIN_SYSCALL __NR_O32_Linux #define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + __NR_Linux_syscalls) #define MAX_SYSCALL MAX_PUBLIC_SYSCALL -#elif defined(__mips__) && (_MIPS_SIM == _ABI64) +#elif defined(__mips64__) -#error "Add support to header file" +#include // for __NR_64_Linux and __NR_64_Linux_syscalls +#define MIN_SYSCALL __NR_64_Linux +#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + __NR_64_Linux_syscalls) +#define MAX_SYSCALL MAX_PUBLIC_SYSCALL #elif defined(__aarch64__) diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h index af70f21..e4e8142 100644 --- a/sandbox/linux/bpf_dsl/seccomp_macros.h +++ b/sandbox/linux/bpf_dsl/seccomp_macros.h @@ -190,7 +190,7 @@ typedef user_regs regs_struct; #define SECCOMP_PT_PARM5(_regs) (_regs).REG_r4 #define SECCOMP_PT_PARM6(_regs) (_regs).REG_r5 -#elif defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) +#elif defined(__mips32__) #define SECCOMP_ARCH AUDIT_ARCH_MIPSEL #define SYSCALL_EIGHT_ARGS // MIPS sigcontext_t is different from i386/x86_64 and ARM. @@ -224,7 +224,7 @@ typedef user_regs regs_struct; #define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ 8*(nr) + 0) -// On Mips we don't have structures like user_regs or user_regs_struct in +// On MIPS we don't have structures like user_regs or user_regs_struct in // sys/user.h that we could use, so we just define regs_struct directly. struct regs_struct { unsigned long long regs[32]; @@ -244,6 +244,65 @@ struct regs_struct { #define SECCOMP_PT_PARM3(_regs) (_regs).REG_a2 #define SECCOMP_PT_PARM4(_regs) (_regs).REG_a3 +#elif defined(__mips64__) +#define SECCOMP_ARCH AUDIT_ARCH_MIPSEL64 +#define SYSCALL_EIGHT_ARGS +// MIPS sigcontext_t is different from i386/x86_64 and ARM. +// See in the Linux kernel. +#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[_reg]) +// Based on MIPS n64 ABI syscall convention. +// On MIPS, when an indirect syscall is being made (syscall(__NR_foo)), +// the real identifier (__NR_foo) is not in v0, but in a0. +#define SECCOMP_RESULT(_ctx) SECCOMP_REG(_ctx, 2) +#define SECCOMP_SYSCALL(_ctx) SECCOMP_REG(_ctx, 2) +#define SECCOMP_IP(_ctx) (_ctx)->uc_mcontext.pc +#define SECCOMP_PARM1(_ctx) SECCOMP_REG(_ctx, 4) +#define SECCOMP_PARM2(_ctx) SECCOMP_REG(_ctx, 5) +#define SECCOMP_PARM3(_ctx) SECCOMP_REG(_ctx, 6) +#define SECCOMP_PARM4(_ctx) SECCOMP_REG(_ctx, 7) +#define SECCOMP_PARM5(_ctx) SECCOMP_REG(_ctx, 8) +#define SECCOMP_PARM6(_ctx) SECCOMP_REG(_ctx, 9) +#define SECCOMP_PARM7(_ctx) SECCOMP_REG(_ctx, 10) +#define SECCOMP_PARM8(_ctx) SECCOMP_REG(_ctx, 11) +#define SECCOMP_NR_IDX (offsetof(struct arch_seccomp_data, nr)) +#define SECCOMP_ARCH_IDX (offsetof(struct arch_seccomp_data, arch)) +#define SECCOMP_IP_MSB_IDX (offsetof(struct arch_seccomp_data, \ + instruction_pointer) + 4) +#define SECCOMP_IP_LSB_IDX (offsetof(struct arch_seccomp_data, \ + instruction_pointer) + 0) +#define SECCOMP_ARG_MSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ + 8*(nr) + 4) +#define SECCOMP_ARG_LSB_IDX(nr) (offsetof(struct arch_seccomp_data, args) + \ + 8*(nr) + 0) + +// On MIPS we don't have structures like user_regs or user_regs_struct in +// sys/user.h that we could use, so we just define regs_struct directly. +struct regs_struct { + unsigned long long regs[32]; +}; + +#define REG_a7 regs[11] +#define REG_a6 regs[10] +#define REG_a5 regs[9] +#define REG_a4 regs[8] +#define REG_a3 regs[7] +#define REG_a2 regs[6] +#define REG_a1 regs[5] +#define REG_a0 regs[4] +#define REG_v1 regs[3] +#define REG_v0 regs[2] + +#define SECCOMP_PT_RESULT(_regs) (_regs).REG_v0 +#define SECCOMP_PT_SYSCALL(_regs) (_regs).REG_v0 +#define SECCOMP_PT_PARM1(_regs) (_regs).REG_a0 +#define SECCOMP_PT_PARM2(_regs) (_regs).REG_a1 +#define SECCOMP_PT_PARM3(_regs) (_regs).REG_a2 +#define SECCOMP_PT_PARM4(_regs) (_regs).REG_a3 +#define SECCOMP_PT_PARM5(_regs) (_regs).REG_a4 +#define SECCOMP_PT_PARM6(_regs) (_regs).REG_a5 +#define SECCOMP_PT_PARM7(_regs) (_regs).REG_a6 +#define SECCOMP_PT_PARM8(_regs) (_regs).REG_a7 + #elif defined(__aarch64__) struct regs_struct { unsigned long long regs[31]; diff --git a/sandbox/linux/bpf_dsl/syscall_set.cc b/sandbox/linux/bpf_dsl/syscall_set.cc index 3d61fa3..b975a2b 100644 --- a/sandbox/linux/bpf_dsl/syscall_set.cc +++ b/sandbox/linux/bpf_dsl/syscall_set.cc @@ -14,9 +14,12 @@ namespace sandbox { namespace { -#if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) +#if defined(__mips32__) // This is true for Mips O32 ABI. static_assert(MIN_SYSCALL == __NR_Linux, "min syscall number should be 4000"); +#elif defined(__mips64__) +// This is true for MIPS N64 ABI. +static_assert(MIN_SYSCALL == __NR_Linux, "min syscall number should be 5000"); #else // This true for supported architectures (Intel and ARM EABI). static_assert(MIN_SYSCALL == 0u, diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc index 4889a9a..d06e765 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc @@ -86,7 +86,7 @@ bool IsBaselinePolicyWatched(int sysno) { SyscallSets::IsNuma(sysno) || SyscallSets::IsPrctl(sysno) || SyscallSets::IsProcessGroupOrSession(sysno) || -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) SyscallSets::IsSocketCall(sysno) || #endif #if defined(__arm__) @@ -147,7 +147,7 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno, if (sysno == __NR_fcntl) return RestrictFcntlCommands(); -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) if (sysno == __NR_fcntl64) return RestrictFcntlCommands(); #endif @@ -191,7 +191,7 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno, return RestrictMmapFlags(); #endif -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) if (sysno == __NR_mmap2) return RestrictMmapFlags(); #endif @@ -241,7 +241,7 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno, return Error(EPERM); } -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) if (SyscallSets::IsSocketCall(sysno)) return RestrictSocketcallCommand(); #endif diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc index e6c64de..68890d2 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc @@ -95,7 +95,7 @@ void PrintSyscallError(uint32_t sysno) { sysno_base10[i] = '0' + mod; } -#if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32) +#if defined(__mips32__) static const char kSeccompErrorPrefix[] = __FILE__ ":**CRASHING**:" SECCOMP_MESSAGE_COMMON_CONTENT " in syscall 4000 + "; #else diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc index 1d9f95c..9f1cdef 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc @@ -28,7 +28,7 @@ bool SyscallSets::IsKill(int sysno) { bool SyscallSets::IsAllowedGettime(int sysno) { switch (sysno) { case __NR_gettimeofday: -#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) +#if defined(__i386__) || defined(__x86_64__) || defined(__mips32__) case __NR_time: #endif return true; @@ -38,11 +38,11 @@ bool SyscallSets::IsAllowedGettime(int sysno) { case __NR_clock_gettime: case __NR_clock_nanosleep: // Could be allowed. case __NR_clock_settime: // Privileged. -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_ftime: // Obsolete. #endif case __NR_settimeofday: // Privileged. -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_stime: #endif default: @@ -97,7 +97,9 @@ bool SyscallSets::IsFileSystem(int sysno) { case __NR_stat: // EPERM not a valid errno. case __NR_symlink: case __NR_unlink: +#if !defined(__mips64__) case __NR_uselib: // Neither EPERM, nor ENOENT are valid errno. +#endif case __NR_ustat: // Same as above. Deprecated. case __NR_utimes: #endif // !defined(__aarch64__) @@ -108,7 +110,7 @@ bool SyscallSets::IsFileSystem(int sysno) { case __NR_fchownat: // Should be called chownat ? #if defined(__x86_64__) || defined(__aarch64__) case __NR_newfstatat: // fstatat(). EPERM not a valid errno. -#elif defined(__i386__) || defined(__arm__) || defined(__mips__) +#elif defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_fstatat64: #endif #if defined(__i386__) || defined(__arm__) @@ -117,7 +119,7 @@ bool SyscallSets::IsFileSystem(int sysno) { case __NR_linkat: case __NR_lookup_dcookie: // ENOENT not a valid errno. -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_lstat64: #endif case __NR_memfd_create: @@ -131,16 +133,16 @@ bool SyscallSets::IsFileSystem(int sysno) { case __NR_readlinkat: case __NR_renameat: case __NR_renameat2: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_stat64: #endif case __NR_statfs: // EPERM not a valid errno. -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_statfs64: #endif case __NR_symlinkat: case __NR_truncate: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_truncate64: #endif case __NR_unlinkat: @@ -157,7 +159,7 @@ bool SyscallSets::IsFileSystem(int sysno) { bool SyscallSets::IsAllowedFileSystemAccessViaFd(int sysno) { switch (sysno) { case __NR_fstat: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_fstat64: #endif return true; @@ -174,7 +176,7 @@ bool SyscallSets::IsAllowedFileSystemAccessViaFd(int sysno) { case __NR_fdatasync: // EPERM not a valid errno. case __NR_flock: // EPERM not a valid errno. case __NR_fstatfs: // Give information about the whole filesystem. -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_fstatfs64: #endif case __NR_fsync: // EPERM not a valid errno. @@ -202,14 +204,14 @@ bool SyscallSets::IsDeniedFileSystemAccessViaFd(int sysno) { #if defined(__i386__) || defined(__arm__) case __NR_fchown32: #endif -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_ftruncate64: #endif #if !defined(__aarch64__) case __NR_getdents: // EPERM not a valid errno. #endif case __NR_getdents64: // EPERM not a valid errno. -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_readdir: #endif return true; @@ -299,7 +301,7 @@ bool SyscallSets::IsAllowedSignalHandling(int sysno) { case __NR_rt_sigaction: case __NR_rt_sigprocmask: case __NR_rt_sigreturn: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_sigaction: case __NR_sigprocmask: case __NR_sigreturn: @@ -315,11 +317,11 @@ bool SyscallSets::IsAllowedSignalHandling(int sysno) { case __NR_signalfd: #endif case __NR_signalfd4: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_sigpending: case __NR_sigsuspend: #endif -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_signal: case __NR_sgetmask: // Obsolete. case __NR_ssetmask: @@ -343,7 +345,7 @@ bool SyscallSets::IsAllowedOperationOnFd(int sysno) { #endif return true; case __NR_fcntl: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_fcntl64: #endif default: @@ -460,12 +462,14 @@ bool SyscallSets::IsDeniedGetOrModifySocket(int sysno) { } } -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) // Big multiplexing system call for sockets. bool SyscallSets::IsSocketCall(int sysno) { switch (sysno) { +#if !defined(__mips64__) case __NR_socketcall: return true; +#endif default: return false; } @@ -500,10 +504,10 @@ bool SyscallSets::IsAllowedAddressSpaceAccess(int sysno) { defined(__aarch64__) case __NR_mmap: #endif -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_mmap2: #endif -#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) +#if defined(__i386__) || defined(__x86_64__) || defined(__mips32__) case __NR_modify_ldt: #endif case __NR_mprotect: @@ -524,7 +528,7 @@ bool SyscallSets::IsAllowedAddressSpaceAccess(int sysno) { bool SyscallSets::IsAllowedGeneralIo(int sysno) { switch (sysno) { case __NR_lseek: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR__llseek: #endif #if !defined(__aarch64__) @@ -534,7 +538,7 @@ bool SyscallSets::IsAllowedGeneralIo(int sysno) { case __NR_pselect6: case __NR_read: case __NR_readv: -#if defined(__arm__) || defined(__mips__) +#if defined(__arm__) || defined(__mips32__) case __NR_recv: #endif #if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \ @@ -548,7 +552,7 @@ bool SyscallSets::IsAllowedGeneralIo(int sysno) { #if defined(__i386__) || defined(__arm__) || defined(__mips__) case __NR__newselect: #endif -#if defined(__arm__) || defined(__mips__) +#if defined(__arm__) || defined(__mips32__) case __NR_send: #endif #if defined(__x86_64__) || defined(__arm__) || defined(__mips__) || \ @@ -566,7 +570,7 @@ bool SyscallSets::IsAllowedGeneralIo(int sysno) { case __NR_pwritev: case __NR_recvmmsg: // Could specify source. case __NR_sendfile: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_sendfile64: #endif case __NR_sendmmsg: // Could specify destination. @@ -608,7 +612,7 @@ bool SyscallSets::IsAllowedBasicScheduler(int sysno) { case __NR_nanosleep: return true; case __NR_getpriority: -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_nice: #endif case __NR_setpriority: @@ -619,7 +623,7 @@ bool SyscallSets::IsAllowedBasicScheduler(int sysno) { bool SyscallSets::IsAdminOperation(int sysno) { switch (sysno) { -#if defined(__i386__) || defined(__arm__) || defined(__mips__) +#if defined(__i386__) || defined(__arm__) || defined(__mips32__) case __NR_bdflush: #endif case __NR_kexec_load: @@ -667,7 +671,7 @@ bool SyscallSets::IsFsControl(int sysno) { case __NR_quotactl: case __NR_swapoff: case __NR_swapon: -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_umount: #endif case __NR_umount2: @@ -718,7 +722,7 @@ bool SyscallSets::IsGlobalProcessEnvironment(int sysno) { #if defined(__i386__) || defined(__arm__) case __NR_ugetrlimit: #endif -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_ulimit: #endif case __NR_getrusage: @@ -799,10 +803,9 @@ bool SyscallSets::IsKeyManagement(int sysno) { } } -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) -bool SyscallSets::IsSystemVSemaphores(int sysno) { - switch (sysno) { - case __NR_semctl: +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__mips64__) +bool SyscallSets::IsSystemVSemaphores(int sysno) { switch (sysno) { case __NR_semctl: case __NR_semget: case __NR_semop: case __NR_semtimedop: @@ -813,7 +816,8 @@ bool SyscallSets::IsSystemVSemaphores(int sysno) { } #endif -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__mips64__) // These give a lot of ambient authority and bypass the setuid sandbox. bool SyscallSets::IsSystemVSharedMemory(int sysno) { switch (sysno) { @@ -828,7 +832,8 @@ bool SyscallSets::IsSystemVSharedMemory(int sysno) { } #endif -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__mips64__) bool SyscallSets::IsSystemVMessageQueue(int sysno) { switch (sysno) { case __NR_msgctl: @@ -842,12 +847,14 @@ bool SyscallSets::IsSystemVMessageQueue(int sysno) { } #endif -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) // Big system V multiplexing system call. bool SyscallSets::IsSystemVIpc(int sysno) { switch (sysno) { +#if !defined(__mips64__) case __NR_ipc: return true; +#endif default: return false; } @@ -855,10 +862,11 @@ bool SyscallSets::IsSystemVIpc(int sysno) { #endif bool SyscallSets::IsAnySystemV(int sysno) { -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) \ + || defined(__mips64__) return IsSystemVMessageQueue(sysno) || IsSystemVSemaphores(sysno) || IsSystemVSharedMemory(sysno); -#elif defined(__i386__) || defined(__mips__) +#elif defined(__i386__) || defined(__mips32__) return IsSystemVIpc(sysno); #endif } @@ -973,13 +981,13 @@ bool SyscallSets::IsMisc(int sysno) { #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) case __NR_afs_syscall: #endif -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_break: #endif #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) case __NR_getpmsg: #endif -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_gtty: case __NR_idle: case __NR_lock: @@ -993,7 +1001,7 @@ bool SyscallSets::IsMisc(int sysno) { #if defined(__x86_64__) case __NR_security: #endif -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) case __NR_stty: #endif #if defined(__x86_64__) @@ -1048,7 +1056,9 @@ bool SyscallSets::IsMipsPrivate(int sysno) { bool SyscallSets::IsMipsMisc(int sysno) { switch (sysno) { case __NR_sysmips: +#if !defined(__mips64__) case __NR_unused150: +#endif return true; default: return false; diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h index 5ba6335..c31d5e9 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h @@ -42,7 +42,7 @@ class SANDBOX_EXPORT SyscallSets { static bool IsAllowedGetOrModifySocket(int sysno); static bool IsDeniedGetOrModifySocket(int sysno); -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) // Big multiplexing system call for sockets. static bool IsSocketCall(int sysno); #endif @@ -70,19 +70,22 @@ class SANDBOX_EXPORT SyscallSets { // Asynchronous I/O API. static bool IsAsyncIo(int sysno); static bool IsKeyManagement(int sysno); -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__mips64__) static bool IsSystemVSemaphores(int sysno); #endif -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__mips64__) // These give a lot of ambient authority and bypass the setuid sandbox. static bool IsSystemVSharedMemory(int sysno); #endif -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__mips64__) static bool IsSystemVMessageQueue(int sysno); #endif -#if defined(__i386__) || defined(__mips__) +#if defined(__i386__) || defined(__mips32__) // Big system V multiplexing system call. static bool IsSystemVIpc(int sysno); #endif diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc index 4d55936..d6db70f 100644 --- a/sandbox/linux/seccomp-bpf/syscall.cc +++ b/sandbox/linux/seccomp-bpf/syscall.cc @@ -188,7 +188,7 @@ asm(// We need to be able to tell the kernel exactly where we made a ".fnend\n" #endif "9:.size SyscallAsm, 9b-SyscallAsm\n" -#elif defined(__mips__) +#elif defined(__mips32__) ".text\n" ".option pic2\n" ".align 4\n" @@ -240,6 +240,53 @@ asm(// We need to be able to tell the kernel exactly where we made a ".set pop\n" ".end SyscallAsm\n" ".size SyscallAsm,.-SyscallAsm\n" +#elif defined(__mips64__) + ".text\n" + ".option pic2\n" + ".global SyscallAsm\n" + ".type SyscallAsm, @function\n" + "SyscallAsm:.ent SyscallAsm\n" + ".frame $sp, 16, $ra\n" + ".set push\n" + ".set noreorder\n" + "daddiu $sp, $sp, -16\n" + ".cpsetup $25, 0, SyscallAsm\n" + "sd $ra, 8($sp)\n" + // Check if "v0" is negative. If so, do not attempt to make a + // system call. Instead, compute the return address that is visible + // to the kernel after we execute "syscall". This address can be + // used as a marker that BPF code inspects. + "bgez $v0, 1f\n" + " nop\n" + // This is equivalent to "la $v0, 2f". + // LA macro has to be avoided since LLVM-AS has issue with LA in PIC mode + // https://llvm.org/bugs/show_bug.cgi?id=27644 + "ld $v0, %got(2f)($gp)\n" + "daddiu $v0, $v0, %lo(2f)\n" + "b 2f\n" + " nop\n" + // On MIPS N64 all eight arguments go to registers a0 - a7 + // We can go ahead and directly copy the entries from the arguments array + // into the appropriate CPU registers. + "1:ld $a7, 56($a0)\n" + "ld $a6, 48($a0)\n" + "ld $a5, 40($a0)\n" + "ld $a4, 32($a0)\n" + "ld $a3, 24($a0)\n" + "ld $a2, 16($a0)\n" + "ld $a1, 8($a0)\n" + "ld $a0, 0($a0)\n" + // Enter the kernel + "syscall\n" + // This is our "magic" return address that the BPF filter sees. + // Restore the return address from the stack. + "2:ld $ra, 8($sp)\n" + ".cpreturn\n" + "jr $ra\n" + "daddiu $sp, $sp, 16\n" + ".set pop\n" + ".end SyscallAsm\n" + ".size SyscallAsm,.-SyscallAsm\n" #elif defined(__aarch64__) ".text\n" ".align 2\n" @@ -358,7 +405,7 @@ intptr_t Syscall::Call(int nr, ret = inout; } #elif defined(__mips__) - int err_status; + intptr_t err_status; intptr_t ret = Syscall::SandboxSyscallRaw(nr, args, &err_status); if (err_status) { diff --git a/sandbox/linux/system_headers/linux_seccomp.h b/sandbox/linux/system_headers/linux_seccomp.h index 3deb3d2..a60fe2a 100644 --- a/sandbox/linux/system_headers/linux_seccomp.h +++ b/sandbox/linux/system_headers/linux_seccomp.h @@ -48,6 +48,9 @@ #ifndef AUDIT_ARCH_MIPSEL #define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE) #endif +#ifndef AUDIT_ARCH_MIPSEL64 +#define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#endif #ifndef AUDIT_ARCH_AARCH64 #define AUDIT_ARCH_AARCH64 (EM_AARCH64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE) #endif diff --git a/sandbox/linux/system_headers/linux_signal.h b/sandbox/linux/system_headers/linux_signal.h index fb9a47b..5ac4fdb 100644 --- a/sandbox/linux/system_headers/linux_signal.h +++ b/sandbox/linux/system_headers/linux_signal.h @@ -116,13 +116,20 @@ typedef siginfo_t LinuxSigInfo; #endif // !defined(__native_client_nonsfi__) // struct sigset_t is different size in PNaCl from the Linux's. -#if defined(__mips__) +#if defined(__mips32__) #if !defined(_NSIG_WORDS) #define _NSIG_WORDS 4 #endif struct LinuxSigSet { unsigned long sig[_NSIG_WORDS]; }; +#elif defined(__mips64__) +#if !defined(_NSIG_WORDS) +#define _NSIG_WORDS 2 +#endif +struct LinuxSigSet { + unsigned long sig[_NSIG_WORDS]; +}; #else typedef uint64_t LinuxSigSet; #endif diff --git a/sandbox/linux/system_headers/linux_syscalls.h b/sandbox/linux/system_headers/linux_syscalls.h index 2b441e4..761c08a 100644 --- a/sandbox/linux/system_headers/linux_syscalls.h +++ b/sandbox/linux/system_headers/linux_syscalls.h @@ -21,11 +21,11 @@ #include "sandbox/linux/system_headers/arm_linux_syscalls.h" #endif -#if defined(__mips__) && (_MIPS_SIM == _ABIO32) +#if defined(__mips32__) #include "sandbox/linux/system_headers/mips_linux_syscalls.h" #endif -#if defined(__mips__) && (_MIPS_SIM == _ABI64) +#if defined(__mips64__) #include "sandbox/linux/system_headers/mips64_linux_syscalls.h" #endif diff --git a/sandbox/linux/system_headers/linux_ucontext.h b/sandbox/linux/system_headers/linux_ucontext.h index ea4d8a6..e97d727 100644 --- a/sandbox/linux/system_headers/linux_ucontext.h +++ b/sandbox/linux/system_headers/linux_ucontext.h @@ -13,8 +13,10 @@ #include "sandbox/linux/system_headers/i386_linux_ucontext.h" #elif defined(__x86_64__) #include "sandbox/linux/system_headers/x86_64_linux_ucontext.h" -#elif defined(__mips__) +#elif defined(__mips32__) #include "sandbox/linux/system_headers/mips_linux_ucontext.h" +#elif defined(__mips64__) +#include "sandbox/linux/system_headers/mips64_linux_ucontext.h" #elif defined(__aarch64__) #include "sandbox/linux/system_headers/arm64_linux_ucontext.h" #else diff --git a/sandbox/linux/system_headers/mips64_linux_syscalls.h b/sandbox/linux/system_headers/mips64_linux_syscalls.h index 90f3d1be..ec75815 100644 --- a/sandbox/linux/system_headers/mips64_linux_syscalls.h +++ b/sandbox/linux/system_headers/mips64_linux_syscalls.h @@ -6,7 +6,7 @@ #ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_SYSCALLS_H_ #define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_SYSCALLS_H_ -#if !defined(__mips__) || (_MIPS_SIM != _ABI64) +#if !defined(__mips__) #error "Including header on wrong architecture" #endif diff --git a/sandbox/linux/system_headers/mips64_linux_ucontext.h b/sandbox/linux/system_headers/mips64_linux_ucontext.h new file mode 100644 index 0000000..3d10479 --- /dev/null +++ b/sandbox/linux/system_headers/mips64_linux_ucontext.h @@ -0,0 +1,50 @@ +// Copyright 2014 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_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_UCONTEXT_H_ + +#include + +// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), +// except we do use sigset_t for uc_sigmask instead of a custom type. +#if !defined(__BIONIC_HAVE_UCONTEXT_T) +// Ensure that 'stack_t' is defined. +#include + +// We also need greg_t for the sandbox, include it in this header as well. +typedef unsigned long greg_t; + +typedef struct { + uint64_t gregs[32]; + uint64_t fpregs[32]; + uint64_t mdhi; + uint64_t hi1; + uint64_t hi2; + uint64_t hi3; + uint64_t mdlo; + uint64_t lo1; + uint64_t lo2; + uint64_t lo3; + uint64_t pc; + uint32_t fpc_csr; + uint32_t used_math; + uint32_t dsp; + uint32_t reserved; +} mcontext_t; + +typedef struct ucontext { + uint32_t uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; + // Other fields are not used by Google Breakpad. Don't define them. +} ucontext_t; + +#else +#include +#endif // __BIONIC_HAVE_UCONTEXT_T + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_UCONTEXT_H_ diff --git a/sandbox/linux/system_headers/mips_linux_syscalls.h b/sandbox/linux/system_headers/mips_linux_syscalls.h index 784d6b8..ddbf97f 100644 --- a/sandbox/linux/system_headers/mips_linux_syscalls.h +++ b/sandbox/linux/system_headers/mips_linux_syscalls.h @@ -6,7 +6,7 @@ #ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_SYSCALLS_H_ #define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_SYSCALLS_H_ -#if !defined(__mips__) || (_MIPS_SIM != _ABIO32) +#if !defined(__mips__) #error "Including header on wrong architecture" #endif