Merge from Chromium at DEPS revision 288042

This commit was generated by merge_to_master.py.

Change-Id: I583602ff16d735199f1810565c9296e970ce2854
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
index bd18412..eaa9ff3 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
@@ -134,6 +134,16 @@
   BPF_ASSERT(ENOSYS == errno);
 }
 
+const char kHelloMessage[] = "Hello";
+
+BPF_DEATH_TEST_C(BPFTest,
+                 BPFDeathTestWithInlineTest,
+                 DEATH_MESSAGE(kHelloMessage),
+                 EnosysPtracePolicy) {
+  LOG(ERROR) << kHelloMessage;
+  _exit(1);
+}
+
 }  // namespace
 
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/errorcode.h b/sandbox/linux/seccomp-bpf/errorcode.h
index 2e51381..2cc001c 100644
--- a/sandbox/linux/seccomp-bpf/errorcode.h
+++ b/sandbox/linux/seccomp-bpf/errorcode.h
@@ -41,9 +41,14 @@
     //       indicate success, but it won't actually run the system call.
     //       This is very different from return ERR_ALLOWED.
     ERR_MIN_ERRNO = 0,
+#if defined(__mips__)
+    // MIPS only supports errno up to 1133
+    ERR_MAX_ERRNO = 1133,
+#else
     // TODO(markus): Android only supports errno up to 255
     // (crbug.com/181647).
     ERR_MAX_ERRNO = 4095,
+#endif
   };
 
   // While BPF filter programs always operate on 32bit quantities, the kernel
diff --git a/sandbox/linux/seccomp-bpf/linux_seccomp.h b/sandbox/linux/seccomp-bpf/linux_seccomp.h
index b3d7a55..1716655 100644
--- a/sandbox/linux/seccomp-bpf/linux_seccomp.h
+++ b/sandbox/linux/seccomp-bpf/linux_seccomp.h
@@ -23,6 +23,10 @@
 #if !defined(__BIONIC__) || defined(__x86_64__)
 #include <sys/types.h>  // Fix for gcc 4.7, make sure __uint16_t is defined.
 #include <sys/user.h>
+#if defined(__mips__)
+// sys/user.h in eglibc misses size_t definition
+#include <stddef.h>
+#endif
 #endif
 
 // For audit.h
@@ -35,6 +39,9 @@
 #ifndef EM_X86_64
 #define EM_X86_64 62
 #endif
+#ifndef EM_MIPS
+#define EM_MIPS   8
+#endif
 
 #ifndef __AUDIT_ARCH_64BIT
 #define __AUDIT_ARCH_64BIT 0x80000000
@@ -51,6 +58,9 @@
 #ifndef AUDIT_ARCH_X86_64
 #define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 #endif
+#ifndef AUDIT_ARCH_MIPSEL
+#define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE)
+#endif
 
 // For prctl.h
 #ifndef PR_SET_SECCOMP
@@ -287,6 +297,63 @@
 #define SECCOMP_PT_PARM5(_regs)   (_regs).REG_r4
 #define SECCOMP_PT_PARM6(_regs)   (_regs).REG_r5
 
+#elif defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)
+#define MIN_SYSCALL         __NR_O32_Linux
+#define MAX_PUBLIC_SYSCALL  (MIN_SYSCALL + __NR_Linux_syscalls)
+#define MAX_SYSCALL         MAX_PUBLIC_SYSCALL
+#define SECCOMP_ARCH        AUDIT_ARCH_MIPSEL
+#define SYSCALL_EIGHT_ARGS
+// MIPS sigcontext_t is different from i386/x86_64 and ARM.
+// See </arch/mips/include/uapi/asm/sigcontext.h> in the Linux kernel.
+#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[_reg])
+// Based on MIPS o32 ABI syscall convention.
+// On MIPS, when indirect syscall is being made (syscall(__NR_foo)),
+// real identificator (__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)
+// Only the first 4 arguments of syscall are in registers.
+// The rest are on the stack.
+#define SECCOMP_STACKPARM(_ctx, n)  (((long *)SECCOMP_REG(_ctx, 29))[(n)])
+#define SECCOMP_PARM5(_ctx)         SECCOMP_STACKPARM(_ctx, 4)
+#define SECCOMP_PARM6(_ctx)         SECCOMP_STACKPARM(_ctx, 5)
+#define SECCOMP_PARM7(_ctx)         SECCOMP_STACKPARM(_ctx, 6)
+#define SECCOMP_PARM8(_ctx)         SECCOMP_STACKPARM(_ctx, 7)
+#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_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
+
 #else
 #error Unsupported target platform
 
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
index 95fcbc6..c25d6cf 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
@@ -13,6 +13,7 @@
 #include <sys/types.h>
 #include <sys/utsname.h>
 #include <unistd.h>
+#include <sys/socket.h>
 
 #if defined(ANDROID)
 // Work-around for buggy headers in Android's NDK
@@ -246,11 +247,8 @@
 ErrorCode ErrnoTestPolicy::EvaluateSyscall(SandboxBPF*, int sysno) const {
   DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
   switch (sysno) {
-#if defined(ANDROID)
     case __NR_dup3:    // dup2 is a wrapper of dup3 in android
-#else
     case __NR_dup2:
-#endif
       // Pretend that dup2() worked, but don't actually do anything.
       return ErrorCode(0);
     case __NR_setuid:
@@ -662,7 +660,7 @@
   // more complex uses of signals where our use of the SIGBUS mask is not
   // 100% transparent. This is expected behavior.
   int fds[2];
-  BPF_ASSERT(pipe(fds) == 0);
+  BPF_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
   bus_handler_fd_ = fds[1];
   struct sigaction sa = {};
   sa.sa_sigaction = SigBusHandler;
@@ -760,15 +758,13 @@
   BPF_ASSERT(aux);
   BrokerProcess* broker_process = static_cast<BrokerProcess*>(aux);
   switch (args.nr) {
-#if defined(ANDROID)
     case __NR_faccessat:    // access is a wrapper of faccessat in android
+      BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD);
       return broker_process->Access(reinterpret_cast<const char*>(args.args[1]),
                                     static_cast<int>(args.args[2]));
-#else
     case __NR_access:
       return broker_process->Access(reinterpret_cast<const char*>(args.args[0]),
                                     static_cast<int>(args.args[1]));
-#endif
     case __NR_open:
       return broker_process->Open(reinterpret_cast<const char*>(args.args[0]),
                                   static_cast<int>(args.args[1]));
@@ -792,11 +788,8 @@
   }
 
   switch (sysno) {
-#if defined(ANDROID)
     case __NR_faccessat:
-#else
     case __NR_access:
-#endif
     case __NR_open:
     case __NR_openat:
       // We get a InitializedOpenBroker class, but our trap handler wants
@@ -874,28 +867,23 @@
   // We deliberately return unusual errno values upon failure, so that we
   // can uniquely test for these values. In a "real" policy, you would want
   // to return more traditional values.
+  int flags_argument_position = -1;
   switch (sysno) {
-#if defined(ANDROID)
-    case __NR_openat:    // open is a wrapper of openat in android
-      // Allow opening files for reading, but don't allow writing.
-      COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_be_all_zero_bits);
-      return sandbox->Cond(2,
-                           ErrorCode::TP_32BIT,
-                           ErrorCode::OP_HAS_ANY_BITS,
-                           O_ACCMODE /* 0x3 */,
-                           ErrorCode(EROFS),
-                           ErrorCode(ErrorCode::ERR_ALLOWED));
-#else
     case __NR_open:
+    case __NR_openat:  // open can be a wrapper for openat(2).
+      if (sysno == __NR_open) {
+        flags_argument_position = 1;
+      } else if (sysno == __NR_openat) {
+        flags_argument_position = 2;
+      }
       // Allow opening files for reading, but don't allow writing.
       COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_be_all_zero_bits);
-      return sandbox->Cond(1,
+      return sandbox->Cond(flags_argument_position,
                            ErrorCode::TP_32BIT,
                            ErrorCode::OP_HAS_ANY_BITS,
                            O_ACCMODE /* 0x3 */,
                            ErrorCode(EROFS),
                            ErrorCode(ErrorCode::ERR_ALLOWED));
-#endif
     case __NR_prctl:
       // Allow prctl(PR_SET_DUMPABLE) and prctl(PR_GET_DUMPABLE), but
       // disallow everything else.
@@ -1990,6 +1978,13 @@
   return;
 #endif
 
+#if defined(__mips__)
+  // TODO: Figure out how to support specificity of handling indirect syscalls
+  //        in this test and enable it.
+  printf("This test is currently disabled on MIPS.");
+  return;
+#endif
+
   pid_t pid = fork();
   BPF_ASSERT_NE(-1, pid);
   if (pid == 0) {
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index 0a028b7..b0a41b0 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -9,11 +9,20 @@
 
 #include "base/basictypes.h"
 #include "base/logging.h"
+#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
 
 namespace sandbox {
 
 namespace {
 
+#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \
+    defined(ARCH_CPU_MIPS_FAMILY)
+// Number that's not currently used by any Linux kernel ABIs.
+const int kInvalidSyscallNumber = 0x351d3;
+#else
+#error Unrecognized architecture
+#endif
+
 asm(// We need to be able to tell the kernel exactly where we made a
     // system call. The C++ compiler likes to sometimes clone or
     // inline code, which would inadvertently end up duplicating
@@ -50,10 +59,10 @@
     // that are used internally (e.g. %ebx for position-independent
     // code, and %ebp for the frame pointer), and as we need to keep at
     // least a few registers available for the register allocator.
-    "1:push %esi; .cfi_adjust_cfa_offset 4\n"
-    "push %edi; .cfi_adjust_cfa_offset 4\n"
-    "push %ebx; .cfi_adjust_cfa_offset 4\n"
-    "push %ebp; .cfi_adjust_cfa_offset 4\n"
+    "1:push %esi; .cfi_adjust_cfa_offset 4; .cfi_rel_offset esi, 0\n"
+    "push %edi; .cfi_adjust_cfa_offset 4; .cfi_rel_offset edi, 0\n"
+    "push %ebx; .cfi_adjust_cfa_offset 4; .cfi_rel_offset ebx, 0\n"
+    "push %ebp; .cfi_adjust_cfa_offset 4; .cfi_rel_offset ebp, 0\n"
     // Copy entries from the array holding the arguments into the
     // correct CPU registers.
     "movl  0(%edi), %ebx\n"
@@ -68,10 +77,10 @@
     "2:"
     // Restore any clobbered registers that we didn't declare to the
     // compiler.
-    "pop  %ebp; .cfi_adjust_cfa_offset -4\n"
-    "pop  %ebx; .cfi_adjust_cfa_offset -4\n"
-    "pop  %edi; .cfi_adjust_cfa_offset -4\n"
-    "pop  %esi; .cfi_adjust_cfa_offset -4\n"
+    "pop  %ebp; .cfi_restore ebp; .cfi_adjust_cfa_offset -4\n"
+    "pop  %ebx; .cfi_restore ebx; .cfi_adjust_cfa_offset -4\n"
+    "pop  %edi; .cfi_restore edi; .cfi_adjust_cfa_offset -4\n"
+    "pop  %esi; .cfi_restore esi; .cfi_adjust_cfa_offset -4\n"
     "ret\n"
     ".cfi_endproc\n"
     "9:.size SyscallAsm, 9b-SyscallAsm\n"
@@ -171,11 +180,61 @@
 #endif
     ".fnend\n"
     "9:.size SyscallAsm, 9b-SyscallAsm\n"
+#elif defined(__mips__)
+    ".text\n"
+    ".align 4\n"
+    ".type SyscallAsm, @function\n"
+    "SyscallAsm:.ent SyscallAsm\n"
+    ".frame  $sp, 40, $ra\n"
+    ".set   push\n"
+    ".set   noreorder\n"
+    "addiu  $sp, $sp, -40\n"
+    "sw     $ra, 36($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"
+    "la     $v0, 2f\n"
+    "b      2f\n"
+    " nop\n"
+    // On MIPS first four arguments go to registers a0 - a3 and any
+    // argument after that goes to stack. We can go ahead and directly
+    // copy the entries from the arguments array into the appropriate
+    // CPU registers and on the stack.
+    "1:lw     $a3, 28($a0)\n"
+    "lw     $a2, 24($a0)\n"
+    "lw     $a1, 20($a0)\n"
+    "lw     $t0, 16($a0)\n"
+    "sw     $a3, 28($sp)\n"
+    "sw     $a2, 24($sp)\n"
+    "sw     $a1, 20($sp)\n"
+    "sw     $t0, 16($sp)\n"
+    "lw     $a3, 12($a0)\n"
+    "lw     $a2, 8($a0)\n"
+    "lw     $a1, 4($a0)\n"
+    "lw     $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:lw     $ra, 36($sp)\n"
+    "jr     $ra\n"
+    " addiu  $sp, $sp, 40\n"
+    ".set    pop\n"
+    ".end    SyscallAsm\n"
+    ".size   SyscallAsm,.-SyscallAsm\n"
 #endif
     );  // asm
 
 }  // namespace
 
+intptr_t Syscall::InvalidCall() {
+  // Explicitly pass eight zero arguments just in case.
+  return Call(kInvalidSyscallNumber, 0, 0, 0, 0, 0, 0, 0, 0);
+}
+
 intptr_t Syscall::Call(int nr,
                        intptr_t p0,
                        intptr_t p1,
@@ -197,11 +256,15 @@
 
   // TODO(nedeljko): Enable use of more than six parameters on architectures
   //                 where that makes sense.
+#if defined(__mips__)
+  const intptr_t args[8] = {p0, p1, p2, p3, p4, p5, p6, p7};
+#else
   DCHECK_EQ(p6, 0) << " Support for syscalls with more than six arguments not "
                       "added for this architecture";
   DCHECK_EQ(p7, 0) << " Support for syscalls with more than six arguments not "
                       "added for this architecture";
   const intptr_t args[6] = {p0, p1, p2, p3, p4, p5};
+#endif  // defined(__mips__)
 
 // Invoke our file-scope assembly code. The constraints have been picked
 // carefully to match what the rest of the assembly code expects in input,
@@ -268,10 +331,64 @@
         );
     ret = inout;
   }
+#elif defined(__mips__)
+  int err_status;
+  intptr_t ret = Syscall::SandboxSyscallRaw(nr, args, &err_status);
+
+  if (err_status) {
+    // On error, MIPS returns errno from syscall instead of -errno.
+    // The purpose of this negation is for SandboxSyscall() to behave
+    // more like it would on other architectures.
+    ret = -ret;
+  }
 #else
 #error "Unimplemented architecture"
 #endif
   return ret;
 }
 
+void Syscall::PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx) {
+#if defined(__mips__)
+  // Mips ABI states that on error a3 CPU register has non zero value and if
+  // there is no error, it should be zero.
+  if (ret_val <= -1 && ret_val >= -4095) {
+    // |ret_val| followes the Syscall::Call() convention of being -errno on
+    // errors. In order to write correct value to return register this sign
+    // needs to be changed back.
+    ret_val = -ret_val;
+    SECCOMP_PARM4(ctx) = 1;
+  } else
+    SECCOMP_PARM4(ctx) = 0;
+#endif
+  SECCOMP_RESULT(ctx) = static_cast<greg_t>(ret_val);
+}
+
+#if defined(__mips__)
+intptr_t Syscall::SandboxSyscallRaw(int nr,
+                                    const intptr_t* args,
+                                    intptr_t* err_ret) {
+  register intptr_t ret __asm__("v0") = nr;
+  // a3 register becomes non zero on error.
+  register intptr_t err_stat __asm__("a3") = 0;
+  {
+    register const intptr_t* data __asm__("a0") = args;
+    asm volatile(
+        "la $t9, SyscallAsm\n"
+        "jalr $t9\n"
+        " nop\n"
+        : "=r"(ret), "=r"(err_stat)
+        : "0"(ret),
+          "r"(data)
+          // a2 is in the clober list so inline assembly can not change its
+          // value.
+        : "memory", "ra", "t9", "a2");
+  }
+
+  // Set an error status so it can be used outside of this function
+  *err_ret = err_stat;
+
+  return ret;
+}
+#endif  // defined(__mips__)
+
 }  // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h
index 10a1253..3686df5 100644
--- a/sandbox/linux/seccomp-bpf/syscall.h
+++ b/sandbox/linux/seccomp-bpf/syscall.h
@@ -5,17 +5,30 @@
 #ifndef SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__
 #define SANDBOX_LINUX_SECCOMP_BPF_SYSCALL_H__
 
+#include <signal.h>
 #include <stdint.h>
 
 #include "base/macros.h"
 #include "sandbox/sandbox_export.h"
 
+// Android's signal.h doesn't define ucontext etc.
+#if defined(OS_ANDROID)
+#include "sandbox/linux/services/android_ucontext.h"
+#endif
+
 namespace sandbox {
 
 // This purely static class can be used to perform system calls with some
 // low-level control.
 class SANDBOX_EXPORT Syscall {
  public:
+  // InvalidCall() invokes Call() with a platform-appropriate syscall
+  // number that is guaranteed to not be implemented (i.e., normally
+  // returns -ENOSYS).
+  // This is primarily meant to be useful for writing sandbox policy
+  // unit tests.
+  static intptr_t InvalidCall();
+
   // System calls can take up to six parameters (up to eight on some
   // architectures). Traditionally, glibc
   // implements this property by using variadic argument lists. This works, but
@@ -112,6 +125,11 @@
     return Call(nr, 0, 0, 0, 0, 0, 0, 0, 0);
   }
 
+  // Set the registers in |ctx| to match what they would be after a system call
+  // returning |ret_val|. |ret_val| must follow the Syscall::Call() convention
+  // of being -errno on errors.
+  static void PutValueInUcontext(intptr_t ret_val, ucontext_t* ctx);
+
  private:
   // This performs system call |nr| with the arguments p0 to p7 from a constant
   // userland address, which is for instance observable by seccomp-bpf filters.
@@ -129,6 +147,21 @@
                        intptr_t p6,
                        intptr_t p7);
 
+#if defined(__mips__)
+  // This function basically does on MIPS what SandboxSyscall() is doing on
+  // other architectures. However, because of specificity of MIPS regarding
+  // handling syscall errors, SandboxSyscall() is made as a wrapper for this
+  // function in order for SandboxSyscall() to behave more like on other
+  // architectures on places where return value from SandboxSyscall() is used
+  // directly (like in most tests).
+  // The syscall "nr" is called with arguments that are set in an array on which
+  // pointer "args" points to and an information weather there is an error or no
+  // is returned to SandboxSyscall() by err_stat.
+  static intptr_t SandboxSyscallRaw(int nr,
+                                    const intptr_t* args,
+                                    intptr_t* err_stat);
+#endif  // defined(__mips__)
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(Syscall);
 };
 
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator.cc b/sandbox/linux/seccomp-bpf/syscall_iterator.cc
index 89cc1cb..d1c383b 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_iterator.cc
@@ -16,14 +16,25 @@
 
   uint32_t val;
   do {
+#if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)
+    // |num_| has been initialized to 4000, which we assume is also MIN_SYSCALL.
+    // This is true for Mips O32 ABI.
+    COMPILE_ASSERT(MIN_SYSCALL == __NR_Linux, min_syscall_should_be_4000);
+#else
     // |num_| has been initialized to 0, which we assume is also MIN_SYSCALL.
     // This true for supported architectures (Intel and ARM EABI).
     COMPILE_ASSERT(MIN_SYSCALL == 0u, min_syscall_should_always_be_zero);
+#endif
     val = num_;
 
+    // The syscall iterator always starts at zero.
+    // If zero is not a valid system call, iterator first returns MIN_SYSCALL -1
+    // before continuing to iterate.
+    if (num_ == 0 && MIN_SYSCALL != num_) {
+      num_ = MIN_SYSCALL - 1;
     // First we iterate up to MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL
     // on Intel architectures, but leaves room for private syscalls on ARM.
-    if (num_ <= MAX_PUBLIC_SYSCALL) {
+    } else if (num_ <= MAX_PUBLIC_SYSCALL) {
       if (invalid_only_ && num_ < MAX_PUBLIC_SYSCALL) {
         num_ = MAX_PUBLIC_SYSCALL;
       } else {
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc
index 08a857a..6d553c8 100644
--- a/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc
@@ -29,7 +29,25 @@
   }
 }
 
-SANDBOX_TEST(SyscallIterator, PublicSyscallRange) {
+#if defined(__mips__)
+SANDBOX_TEST(SyscallIterator, PublicSyscallRangeMIPS) {
+  SyscallIterator iter(false);
+  uint32_t next = iter.Next();
+  SANDBOX_ASSERT(next == 0);
+
+  // Since on MIPS MIN_SYSCALL != 0 we need to move iterator to valid range.
+  next = iter.Next();
+  SANDBOX_ASSERT(next == MIN_SYSCALL - 1);
+
+  // The iterator should cover the public syscall range
+  // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls.
+  for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) {
+    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
+  }
+  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
+}
+#else
+SANDBOX_TEST(SyscallIterator, PublicSyscallRangeIntelArm) {
   SyscallIterator iter(false);
   uint32_t next = iter.Next();
 
@@ -44,6 +62,7 @@
   }
   SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
 }
+#endif  // defined(__mips__)
 
 #if defined(__arm__)
 SANDBOX_TEST(SyscallIterator, ARMPrivateSyscallRange) {
@@ -103,7 +122,27 @@
   }
 }
 
-SANDBOX_TEST(SyscallIterator, InvalidOnly) {
+#if defined(__mips__)
+SANDBOX_TEST(SyscallIterator, InvalidOnlyMIPS) {
+  bool invalid_only = true;
+  SyscallIterator iter(invalid_only);
+  uint32_t next = iter.Next();
+  SANDBOX_ASSERT(next == 0);
+  // For Mips O32 ABI we're assuming MIN_SYSCALL == 4000.
+  SANDBOX_ASSERT(MIN_SYSCALL == 4000);
+
+  // Since on MIPS MIN_SYSCALL != 0, we need to move iterator to valid range
+  // The iterator should skip until the last invalid syscall in this range.
+  next = iter.Next();
+  SANDBOX_ASSERT(next == MIN_SYSCALL - 1);
+  next = iter.Next();
+  // First next invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|.
+  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
+}
+
+#else
+
+SANDBOX_TEST(SyscallIterator, InvalidOnlyIntelArm) {
   bool invalid_only = true;
   SyscallIterator iter(invalid_only);
   uint32_t next = iter.Next();
@@ -128,8 +167,9 @@
     next = iter.Next();
   }
   SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
-#endif
+#endif  // defined(__arm__)
 }
+#endif  // defined(__mips__)
 
 }  // namespace
 
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index 4e142f4..38f31e0 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -33,6 +33,10 @@
 const int kMMapNr = __NR_mmap;
 #endif
 
+TEST(Syscall, InvalidCallReturnsENOSYS) {
+  EXPECT_EQ(-ENOSYS, Syscall::InvalidCall());
+}
+
 TEST(Syscall, WellKnownEntryPoint) {
 // Test that Syscall::Call(-1) is handled specially. Don't do this on ARM,
 // where syscall(-1) crashes with SIGILL. Not running the test is fine, as we
@@ -54,6 +58,9 @@
 #else
   EXPECT_EQ(0xEF000000u, ((uint32_t*)Syscall::Call(-1))[-1]);  // SVC 0
 #endif
+#elif defined(__mips__)
+  // Opcode for MIPS sycall is in the lower 16-bits
+  EXPECT_EQ(0x0cu, (((uint32_t*)Syscall::Call(-1))[-1]) & 0x0000FFFF);
 #else
 #warning Incomplete test case; need port for target platform
 #endif
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index 4c42111..ce906fc 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -150,10 +150,19 @@
   struct arch_sigsys sigsys;
   memcpy(&sigsys, &info->_sifields, sizeof(sigsys));
 
+#if defined(__mips__)
+  // When indirect syscall (syscall(__NR_foo, ...)) is made on Mips, the
+  // number in register SECCOMP_SYSCALL(ctx) is always __NR_syscall and the
+  // real number of a syscall (__NR_foo) is in SECCOMP_PARM1(ctx)
+  bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) &&
+                          sigsys.nr != static_cast<int>(SECCOMP_PARM1(ctx));
+#else
+  bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx));
+#endif
+
   // Some more sanity checks.
   if (sigsys.ip != reinterpret_cast<void*>(SECCOMP_IP(ctx)) ||
-      sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) ||
-      sigsys.arch != SECCOMP_ARCH) {
+      sigsys_nr_is_bad || sigsys.arch != SECCOMP_ARCH) {
     // TODO(markus):
     // SANDBOX_DIE() can call LOG(FATAL). This is not normally async-signal
     // safe and can lead to bugs. We should eventually implement a different
@@ -168,13 +177,28 @@
     if (sigsys.nr == __NR_clone) {
       RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler.");
     }
-    rc = Syscall::Call(sigsys.nr,
+#if defined(__mips__)
+    // Mips supports up to eight arguments for syscall.
+    // However, seccomp bpf can filter only up to six arguments, so using eight
+    // arguments has sense only when using UnsafeTrap() handler.
+    rc = Syscall::Call(SECCOMP_SYSCALL(ctx),
+                       SECCOMP_PARM1(ctx),
+                       SECCOMP_PARM2(ctx),
+                       SECCOMP_PARM3(ctx),
+                       SECCOMP_PARM4(ctx),
+                       SECCOMP_PARM5(ctx),
+                       SECCOMP_PARM6(ctx),
+                       SECCOMP_PARM7(ctx),
+                       SECCOMP_PARM8(ctx));
+#else
+    rc = Syscall::Call(SECCOMP_SYSCALL(ctx),
                        SECCOMP_PARM1(ctx),
                        SECCOMP_PARM2(ctx),
                        SECCOMP_PARM3(ctx),
                        SECCOMP_PARM4(ctx),
                        SECCOMP_PARM5(ctx),
                        SECCOMP_PARM6(ctx));
+#endif  // defined(__mips__)
   } else {
     const ErrorCode& err = trap_array_[info->si_errno - 1];
     if (!err.safe_) {
@@ -185,7 +209,9 @@
     // is what we are showing to TrapFnc callbacks that the system call
     // evaluator registered with the sandbox.
     struct arch_seccomp_data data = {
-        sigsys.nr, SECCOMP_ARCH, reinterpret_cast<uint64_t>(sigsys.ip),
+        static_cast<int>(SECCOMP_SYSCALL(ctx)),
+        SECCOMP_ARCH,
+        reinterpret_cast<uint64_t>(sigsys.ip),
         {static_cast<uint64_t>(SECCOMP_PARM1(ctx)),
          static_cast<uint64_t>(SECCOMP_PARM2(ctx)),
          static_cast<uint64_t>(SECCOMP_PARM3(ctx)),
@@ -201,7 +227,7 @@
   // Update the CPU register that stores the return code of the system call
   // that we just handled, and restore "errno" to the value that it had
   // before entering the signal handler.
-  SECCOMP_RESULT(ctx) = static_cast<greg_t>(rc);
+  Syscall::PutValueInUcontext(rc, ctx);
   errno = old_errno;
 
   return;