Index: sandbox/linux/seccomp-bpf/syscall.cc |
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc |
index fd599e893b2b7d3b3fdefe81dfcfeb8dd17717d4..ee4d89e894b27674078dfbcd8d795e8f5f8bfe23 100644 |
--- a/sandbox/linux/seccomp-bpf/syscall.cc |
+++ b/sandbox/linux/seccomp-bpf/syscall.cc |
@@ -1,7 +1,6 @@ |
// Copyright (c) 2012 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. |
- |
#include "sandbox/linux/seccomp-bpf/syscall.h" |
#include <asm/unistd.h> |
@@ -168,6 +167,47 @@ namespace sandbox { |
#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, 32, $ra\n" |
+ ".set push\n" |
+ ".set noreorder\n" |
+ "addiu $sp, $sp, -32\n" |
+ "sw $ra, 28($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 $t0, 20($a0)\n" |
+ "sw $t0, 20($sp)\n" |
+ "lw $t0, 16($a0)\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, 28($sp)\n" |
+ "jr $ra\n" |
+ " addiu $sp, $sp, 32\n" |
+ ".set pop\n" |
+ ".end SyscallAsm\n" |
+ ".size SyscallAsm,.-SyscallAsm\n" |
#endif |
); // asm |
@@ -233,6 +273,16 @@ intptr_t SandboxSyscall(int nr, |
); |
ret = inout; |
} |
+#elif defined(__mips__) |
+ int err_status; |
+ intptr_t ret = SandboxSyscallRaw(nr, args, &err_status); |
+ |
+ if(err_status) |
jln (very slow on Chromium)
2014/06/03 01:00:33
Nit: space after if and backets {} since it's a m
|
+ // 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 |
errno = ENOSYS; |
intptr_t ret = -1; |
@@ -240,4 +290,30 @@ intptr_t SandboxSyscall(int nr, |
return ret; |
} |
+#if defined(__mips__) |
+intptr_t 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 |