summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authorjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-13 12:59:59 +0000
committerjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-13 12:59:59 +0000
commita24c66d2a9ac204ada9ad3a636256a2ed8c4ad28 (patch)
treef4a0279e8a1f3aba5bc2d0f4dc43570255901a76 /sandbox
parentd87e618b08ffd716085acb367c3837cb1ac90ef5 (diff)
downloadchromium_src-a24c66d2a9ac204ada9ad3a636256a2ed8c4ad28.zip
chromium_src-a24c66d2a9ac204ada9ad3a636256a2ed8c4ad28.tar.gz
chromium_src-a24c66d2a9ac204ada9ad3a636256a2ed8c4ad28.tar.bz2
Clean-up the SandboxSyscall interface
Create a new Syscall class with a static method to replace SandboxSyscall() and clean-up some documentation. BUG=369594 Review URL: https://codereview.chromium.org/330723003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277004 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/linux/seccomp-bpf/die.cc8
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf.cc21
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf.h1
-rw-r--r--sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc44
-rw-r--r--sandbox/linux/seccomp-bpf/syscall.cc391
-rw-r--r--sandbox/linux/seccomp-bpf/syscall.h203
-rw-r--r--sandbox/linux/seccomp-bpf/syscall_unittest.cc115
-rw-r--r--sandbox/linux/seccomp-bpf/trap.cc16
8 files changed, 388 insertions, 411 deletions
diff --git a/sandbox/linux/seccomp-bpf/die.cc b/sandbox/linux/seccomp-bpf/die.cc
index 533e2e9..e5bc7c9 100644
--- a/sandbox/linux/seccomp-bpf/die.cc
+++ b/sandbox/linux/seccomp-bpf/die.cc
@@ -22,7 +22,7 @@ void Die::ExitGroup() {
// Especially, since we are dealing with system call filters. Continuing
// execution would be very bad in most cases where ExitGroup() gets called.
// So, we'll try a few other strategies too.
- SandboxSyscall(__NR_exit_group, 1);
+ Syscall::Call(__NR_exit_group, 1);
// We have no idea what our run-time environment looks like. So, signal
// handlers might or might not do the right thing. Try to reset settings
@@ -30,7 +30,7 @@ void Die::ExitGroup() {
// succeeded in doing so. Nonetheless, triggering a fatal signal could help
// us terminate.
signal(SIGSEGV, SIG_DFL);
- SandboxSyscall(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0);
+ Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0);
if (*(volatile char*)0) {
}
@@ -40,7 +40,7 @@ void Die::ExitGroup() {
// We in fact retry the system call inside of our loop so that it will
// stand out when somebody tries to diagnose the problem by using "strace".
for (;;) {
- SandboxSyscall(__NR_exit_group, 1);
+ Syscall::Call(__NR_exit_group, 1);
}
}
@@ -75,7 +75,7 @@ void Die::LogToStderr(const char* msg, const char* file, int line) {
// No need to loop. Short write()s are unlikely and if they happen we
// probably prefer them over a loop that blocks.
ignore_result(
- HANDLE_EINTR(SandboxSyscall(__NR_write, 2, s.c_str(), s.length())));
+ HANDLE_EINTR(Syscall::Call(__NR_write, 2, s.c_str(), s.length())));
}
}
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index c5c6f61..6ecbca9 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -613,7 +613,7 @@ SandboxBPF::Program* SandboxBPF::AssembleFilter(bool force_verification) {
// and of course, we make sure to only ever enable this feature if it
// is actually requested by the sandbox policy.
if (has_unsafe_traps) {
- if (SandboxSyscall(-1) == -1 && errno == ENOSYS) {
+ if (Syscall::Call(-1) == -1 && errno == ENOSYS) {
SANDBOX_DIE(
"Support for UnsafeTrap() has not yet been ported to this "
"architecture");
@@ -650,9 +650,8 @@ SandboxBPF::Program* SandboxBPF::AssembleFilter(bool force_verification) {
gen->Traverse(jumptable, RedirectToUserspace, this);
// Allow system calls, if they originate from our magic return address
- // (which we can query by calling SandboxSyscall(-1)).
- uintptr_t syscall_entry_point =
- static_cast<uintptr_t>(SandboxSyscall(-1));
+ // (which we can query by calling Syscall::Call(-1)).
+ uintptr_t syscall_entry_point = static_cast<uintptr_t>(Syscall::Call(-1));
uint32_t low = static_cast<uint32_t>(syscall_entry_point);
#if __SIZEOF_POINTER__ > 4
uint32_t hi = static_cast<uint32_t>(syscall_entry_point >> 32);
@@ -1003,13 +1002,13 @@ ErrorCode SandboxBPF::UnsafeTrap(Trap::TrapFnc fnc, const void* aux) {
}
intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) {
- return SandboxSyscall(args.nr,
- static_cast<intptr_t>(args.args[0]),
- static_cast<intptr_t>(args.args[1]),
- static_cast<intptr_t>(args.args[2]),
- static_cast<intptr_t>(args.args[3]),
- static_cast<intptr_t>(args.args[4]),
- static_cast<intptr_t>(args.args[5]));
+ return Syscall::Call(args.nr,
+ static_cast<intptr_t>(args.args[0]),
+ static_cast<intptr_t>(args.args[1]),
+ static_cast<intptr_t>(args.args[2]),
+ static_cast<intptr_t>(args.args[3]),
+ static_cast<intptr_t>(args.args[4]),
+ static_cast<intptr_t>(args.args[5]));
}
ErrorCode SandboxBPF::Cond(int argno,
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
index 9bb414a..32fe2a7 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.h
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.h
@@ -25,6 +25,7 @@
namespace sandbox {
+// This must match the kernel's seccomp_data structure.
struct arch_seccomp_data {
int nr;
uint32_t arch;
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
index 075604d..9f02602 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
@@ -1204,7 +1204,7 @@ class EqualityStressTest {
// based on the system call number and the parameters that we decided
// to pass in. Verify that this condition holds true.
BPF_ASSERT(
- SandboxSyscall(
+ Syscall::Call(
sysno, args[0], args[1], args[2], args[3], args[4], args[5]) ==
-err);
}
@@ -1279,18 +1279,18 @@ ErrorCode EqualityArgumentWidthPolicy::EvaluateSyscall(SandboxBPF* sandbox,
}
BPF_TEST_C(SandboxBPF, EqualityArgumentWidth, EqualityArgumentWidthPolicy) {
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0x55555555) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0, 0xAAAAAAAA) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0, 0x55555555) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0, 0xAAAAAAAA) == -2);
#if __SIZEOF_POINTER__ > 4
// On 32bit machines, there is no way to pass a 64bit argument through the
// syscall interface. So, we have to skip the part of the test that requires
// 64bit arguments.
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555AAAAAAAAULL) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555500000000ULL) == -2);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x5555555511111111ULL) == -2);
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x11111111AAAAAAAAULL) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x55555555AAAAAAAAULL) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x5555555500000000ULL) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x5555555511111111ULL) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x11111111AAAAAAAAULL) == -2);
#else
- BPF_ASSERT(SandboxSyscall(__NR_uname, 1, 0x55555555) == -2);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 1, 0x55555555) == -2);
#endif
}
@@ -1302,7 +1302,7 @@ BPF_DEATH_TEST_C(SandboxBPF,
EqualityArgumentUnallowed64bit,
DEATH_MESSAGE("Unexpected 64bit argument detected"),
EqualityArgumentWidthPolicy) {
- SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL);
+ Syscall::Call(__NR_uname, 0, 0x5555555555555555ULL);
}
#endif
@@ -1330,9 +1330,9 @@ class EqualityWithNegativeArgumentsPolicy : public SandboxBPFPolicy {
BPF_TEST_C(SandboxBPF,
EqualityWithNegativeArguments,
EqualityWithNegativeArgumentsPolicy) {
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, -1) == -1);
- BPF_ASSERT(SandboxSyscall(__NR_uname, -1LL) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0xFFFFFFFF) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, -1) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, -1LL) == -1);
}
#if __SIZEOF_POINTER__ > 4
@@ -1343,7 +1343,7 @@ BPF_DEATH_TEST_C(SandboxBPF,
// When expecting a 32bit system call argument, we look at the MSB of the
// 64bit value and allow both "0" and "-1". But the latter is allowed only
// iff the LSB was negative. So, this death test should error out.
- BPF_ASSERT(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000LL) == -1);
+ BPF_ASSERT(Syscall::Call(__NR_uname, 0xFFFFFFFF00000000LL) == -1);
}
#endif
class AllBitTestPolicy : public SandboxBPFPolicy {
@@ -1433,10 +1433,10 @@ ErrorCode AllBitTestPolicy::EvaluateSyscall(SandboxBPF* sandbox,
// to make changes to these values, you will have to edit the
// test policy instead.
#define BITMASK_TEST(testcase, arg, op, mask, expected_value) \
- BPF_ASSERT(SandboxSyscall(__NR_uname, (testcase), (arg)) == (expected_value))
+ BPF_ASSERT(Syscall::Call(__NR_uname, (testcase), (arg)) == (expected_value))
// Our uname() system call returns ErrorCode(1) for success and
-// ErrorCode(0) for failure. SandboxSyscall() turns this into an
+// ErrorCode(0) for failure. Syscall::Call() turns this into an
// exit code of -1 or 0.
#define EXPECT_FAILURE 0
#define EXPECT_SUCCESS -1
@@ -1866,7 +1866,7 @@ ErrorCode PthreadPolicyBitMask::EvaluateSyscall(SandboxBPF* sandbox,
static void* ThreadFnc(void* arg) {
++*reinterpret_cast<int*>(arg);
- SandboxSyscall(__NR_futex, arg, FUTEX_WAKE, 1, 0, 0, 0);
+ Syscall::Call(__NR_futex, arg, FUTEX_WAKE, 1, 0, 0, 0);
return NULL;
}
@@ -1885,7 +1885,7 @@ static void PthreadTest() {
BPF_ASSERT(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
BPF_ASSERT(!pthread_create(&thread, &attr, ThreadFnc, &thread_ran));
BPF_ASSERT(!pthread_attr_destroy(&attr));
- while (SandboxSyscall(__NR_futex, &thread_ran, FUTEX_WAIT, 0, 0, 0, 0) ==
+ while (Syscall::Call(__NR_futex, &thread_ran, FUTEX_WAIT, 0, 0, 0, 0) ==
-EINTR) {
}
BPF_ASSERT(thread_ran);
@@ -1896,11 +1896,11 @@ static void PthreadTest() {
// run-time libraries other than glibc might call __NR_fork instead of
// __NR_clone, and that would introduce a bogus test failure.
int pid;
- BPF_ASSERT(SandboxSyscall(__NR_clone,
- CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD,
- 0,
- 0,
- &pid) == -EPERM);
+ BPF_ASSERT(Syscall::Call(__NR_clone,
+ CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD,
+ 0,
+ 0,
+ &pid) == -EPERM);
}
BPF_TEST_C(SandboxBPF, PthreadEquality, PthreadPolicyEquality) {
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index fd599e8..64c0b8e 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -11,169 +11,177 @@
namespace sandbox {
- 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
- // the entry point.
- // "gcc" can suppress code duplication with suitable function
- // attributes, but "clang" doesn't have this ability.
- // The "clang" developer mailing list suggested that the correct
- // and portable solution is a file-scope assembly block.
- // N.B. We do mark our code as a proper function so that backtraces
- // work correctly. But we make absolutely no attempt to use the
- // ABI's calling conventions for passing arguments. We will only
- // ever be called from assembly code and thus can pick more
- // suitable calling conventions.
+namespace {
+
+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
+ // the entry point.
+ // "gcc" can suppress code duplication with suitable function
+ // attributes, but "clang" doesn't have this ability.
+ // The "clang" developer mailing list suggested that the correct
+ // and portable solution is a file-scope assembly block.
+ // N.B. We do mark our code as a proper function so that backtraces
+ // work correctly. But we make absolutely no attempt to use the
+ // ABI's calling conventions for passing arguments. We will only
+ // ever be called from assembly code and thus can pick more
+ // suitable calling conventions.
#if defined(__i386__)
- ".text\n"
- ".align 16, 0x90\n"
- ".type SyscallAsm, @function\n"
- "SyscallAsm:.cfi_startproc\n"
- // Check if "%eax" 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 "int $0x80". This address can be
- // used as a marker that BPF code inspects.
- "test %eax, %eax\n"
- "jge 1f\n"
- // Always, make sure that our code is position-independent, or
- // address space randomization might not work on i386. This means,
- // we can't use "lea", but instead have to rely on "call/pop".
- "call 0f; .cfi_adjust_cfa_offset 4\n"
- "0:pop %eax; .cfi_adjust_cfa_offset -4\n"
- "addl $2f-0b, %eax\n"
- "ret\n"
- // Save register that we don't want to clobber. On i386, we need to
- // save relatively aggressively, as there are a couple or registers
- // 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"
- // Copy entries from the array holding the arguments into the
- // correct CPU registers.
- "movl 0(%edi), %ebx\n"
- "movl 4(%edi), %ecx\n"
- "movl 8(%edi), %edx\n"
- "movl 12(%edi), %esi\n"
- "movl 20(%edi), %ebp\n"
- "movl 16(%edi), %edi\n"
- // Enter the kernel.
- "int $0x80\n"
- // This is our "magic" return address that the BPF filter sees.
- "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"
- "ret\n"
- ".cfi_endproc\n"
- "9:.size SyscallAsm, 9b-SyscallAsm\n"
+ ".text\n"
+ ".align 16, 0x90\n"
+ ".type SyscallAsm, @function\n"
+ "SyscallAsm:.cfi_startproc\n"
+ // Check if "%eax" 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 "int $0x80". This address can be
+ // used as a marker that BPF code inspects.
+ "test %eax, %eax\n"
+ "jge 1f\n"
+ // Always, make sure that our code is position-independent, or
+ // address space randomization might not work on i386. This means,
+ // we can't use "lea", but instead have to rely on "call/pop".
+ "call 0f; .cfi_adjust_cfa_offset 4\n"
+ "0:pop %eax; .cfi_adjust_cfa_offset -4\n"
+ "addl $2f-0b, %eax\n"
+ "ret\n"
+ // Save register that we don't want to clobber. On i386, we need to
+ // save relatively aggressively, as there are a couple or registers
+ // 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"
+ // Copy entries from the array holding the arguments into the
+ // correct CPU registers.
+ "movl 0(%edi), %ebx\n"
+ "movl 4(%edi), %ecx\n"
+ "movl 8(%edi), %edx\n"
+ "movl 12(%edi), %esi\n"
+ "movl 20(%edi), %ebp\n"
+ "movl 16(%edi), %edi\n"
+ // Enter the kernel.
+ "int $0x80\n"
+ // This is our "magic" return address that the BPF filter sees.
+ "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"
+ "ret\n"
+ ".cfi_endproc\n"
+ "9:.size SyscallAsm, 9b-SyscallAsm\n"
#elif defined(__x86_64__)
- ".text\n"
- ".align 16, 0x90\n"
- ".type SyscallAsm, @function\n"
- "SyscallAsm:.cfi_startproc\n"
- // Check if "%rax" 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.
- "test %rax, %rax\n"
- "jge 1f\n"
- // Always make sure that our code is position-independent, or the
- // linker will throw a hissy fit on x86-64.
- "call 0f; .cfi_adjust_cfa_offset 8\n"
- "0:pop %rax; .cfi_adjust_cfa_offset -8\n"
- "addq $2f-0b, %rax\n"
- "ret\n"
- // We declared all clobbered registers to the compiler. On x86-64,
- // there really isn't much of a problem with register pressure. So,
- // we can go ahead and directly copy the entries from the arguments
- // array into the appropriate CPU registers.
- "1:movq 0(%r12), %rdi\n"
- "movq 8(%r12), %rsi\n"
- "movq 16(%r12), %rdx\n"
- "movq 24(%r12), %r10\n"
- "movq 32(%r12), %r8\n"
- "movq 40(%r12), %r9\n"
- // Enter the kernel.
- "syscall\n"
- // This is our "magic" return address that the BPF filter sees.
- "2:ret\n"
- ".cfi_endproc\n"
- "9:.size SyscallAsm, 9b-SyscallAsm\n"
+ ".text\n"
+ ".align 16, 0x90\n"
+ ".type SyscallAsm, @function\n"
+ "SyscallAsm:.cfi_startproc\n"
+ // Check if "%rax" 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.
+ "test %rax, %rax\n"
+ "jge 1f\n"
+ // Always make sure that our code is position-independent, or the
+ // linker will throw a hissy fit on x86-64.
+ "call 0f; .cfi_adjust_cfa_offset 8\n"
+ "0:pop %rax; .cfi_adjust_cfa_offset -8\n"
+ "addq $2f-0b, %rax\n"
+ "ret\n"
+ // We declared all clobbered registers to the compiler. On x86-64,
+ // there really isn't much of a problem with register pressure. So,
+ // we can go ahead and directly copy the entries from the arguments
+ // array into the appropriate CPU registers.
+ "1:movq 0(%r12), %rdi\n"
+ "movq 8(%r12), %rsi\n"
+ "movq 16(%r12), %rdx\n"
+ "movq 24(%r12), %r10\n"
+ "movq 32(%r12), %r8\n"
+ "movq 40(%r12), %r9\n"
+ // Enter the kernel.
+ "syscall\n"
+ // This is our "magic" return address that the BPF filter sees.
+ "2:ret\n"
+ ".cfi_endproc\n"
+ "9:.size SyscallAsm, 9b-SyscallAsm\n"
#elif defined(__arm__)
- // Throughout this file, we use the same mode (ARM vs. thumb)
- // that the C++ compiler uses. This means, when transfering control
- // from C++ to assembly code, we do not need to switch modes (e.g.
- // by using the "bx" instruction). It also means that our assembly
- // code should not be invoked directly from code that lives in
- // other compilation units, as we don't bother implementing thumb
- // interworking. That's OK, as we don't make any of the assembly
- // symbols public. They are all local to this file.
- ".text\n"
- ".align 2\n"
- ".type SyscallAsm, %function\n"
+ // Throughout this file, we use the same mode (ARM vs. thumb)
+ // that the C++ compiler uses. This means, when transfering control
+ // from C++ to assembly code, we do not need to switch modes (e.g.
+ // by using the "bx" instruction). It also means that our assembly
+ // code should not be invoked directly from code that lives in
+ // other compilation units, as we don't bother implementing thumb
+ // interworking. That's OK, as we don't make any of the assembly
+ // symbols public. They are all local to this file.
+ ".text\n"
+ ".align 2\n"
+ ".type SyscallAsm, %function\n"
#if defined(__thumb__)
- ".thumb_func\n"
+ ".thumb_func\n"
#else
- ".arm\n"
+ ".arm\n"
#endif
- "SyscallAsm:.fnstart\n"
- "@ args = 0, pretend = 0, frame = 8\n"
- "@ frame_needed = 1, uses_anonymous_args = 0\n"
+ "SyscallAsm:.fnstart\n"
+ "@ args = 0, pretend = 0, frame = 8\n"
+ "@ frame_needed = 1, uses_anonymous_args = 0\n"
#if defined(__thumb__)
- ".cfi_startproc\n"
- "push {r7, lr}\n"
- ".cfi_offset 14, -4\n"
- ".cfi_offset 7, -8\n"
- "mov r7, sp\n"
- ".cfi_def_cfa_register 7\n"
- ".cfi_def_cfa_offset 8\n"
+ ".cfi_startproc\n"
+ "push {r7, lr}\n"
+ ".cfi_offset 14, -4\n"
+ ".cfi_offset 7, -8\n"
+ "mov r7, sp\n"
+ ".cfi_def_cfa_register 7\n"
+ ".cfi_def_cfa_offset 8\n"
#else
- "stmfd sp!, {fp, lr}\n"
- "add fp, sp, #4\n"
+ "stmfd sp!, {fp, lr}\n"
+ "add fp, sp, #4\n"
#endif
- // Check if "r0" 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 "swi 0". This address can be
- // used as a marker that BPF code inspects.
- "cmp r0, #0\n"
- "bge 1f\n"
- "adr r0, 2f\n"
- "b 2f\n"
- // We declared (almost) all clobbered registers to the compiler. On
- // ARM there is no particular register pressure. So, we can go
- // ahead and directly copy the entries from the arguments array
- // into the appropriate CPU registers.
- "1:ldr r5, [r6, #20]\n"
- "ldr r4, [r6, #16]\n"
- "ldr r3, [r6, #12]\n"
- "ldr r2, [r6, #8]\n"
- "ldr r1, [r6, #4]\n"
- "mov r7, r0\n"
- "ldr r0, [r6, #0]\n"
- // Enter the kernel
- "swi 0\n"
- // Restore the frame pointer. Also restore the program counter from
- // the link register; this makes us return to the caller.
+ // Check if "r0" 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 "swi 0". This address can be
+ // used as a marker that BPF code inspects.
+ "cmp r0, #0\n"
+ "bge 1f\n"
+ "adr r0, 2f\n"
+ "b 2f\n"
+ // We declared (almost) all clobbered registers to the compiler. On
+ // ARM there is no particular register pressure. So, we can go
+ // ahead and directly copy the entries from the arguments array
+ // into the appropriate CPU registers.
+ "1:ldr r5, [r6, #20]\n"
+ "ldr r4, [r6, #16]\n"
+ "ldr r3, [r6, #12]\n"
+ "ldr r2, [r6, #8]\n"
+ "ldr r1, [r6, #4]\n"
+ "mov r7, r0\n"
+ "ldr r0, [r6, #0]\n"
+ // Enter the kernel
+ "swi 0\n"
+// Restore the frame pointer. Also restore the program counter from
+// the link register; this makes us return to the caller.
#if defined(__thumb__)
- "2:pop {r7, pc}\n"
- ".cfi_endproc\n"
+ "2:pop {r7, pc}\n"
+ ".cfi_endproc\n"
#else
- "2:ldmfd sp!, {fp, pc}\n"
+ "2:ldmfd sp!, {fp, pc}\n"
#endif
- ".fnend\n"
- "9:.size SyscallAsm, 9b-SyscallAsm\n"
+ ".fnend\n"
+ "9:.size SyscallAsm, 9b-SyscallAsm\n"
#endif
- ); // asm
+ ); // asm
+
+} // namespace
-intptr_t SandboxSyscall(int nr,
- intptr_t p0, intptr_t p1, intptr_t p2,
- intptr_t p3, intptr_t p4, intptr_t p5) {
+intptr_t Syscall::Call(int nr,
+ intptr_t p0,
+ intptr_t p1,
+ intptr_t p2,
+ intptr_t p3,
+ intptr_t p4,
+ intptr_t p5) {
// We rely on "intptr_t" to be the exact size as a "void *". This is
// typically true, but just in case, we add a check. The language
// specification allows platforms some leeway in cases, where
@@ -181,61 +189,78 @@ intptr_t SandboxSyscall(int nr,
// that this would only be an issue for IA64, which we are currently not
// planning on supporting. And it is even possible that this would work
// on IA64, but for lack of actual hardware, I cannot test.
- COMPILE_ASSERT(sizeof(void *) == sizeof(intptr_t),
+ COMPILE_ASSERT(sizeof(void*) == sizeof(intptr_t),
pointer_types_and_intptr_must_be_exactly_the_same_size);
- const intptr_t args[6] = { p0, p1, p2, p3, p4, p5 };
+ const intptr_t args[6] = {p0, p1, p2, p3, p4, p5};
- // Invoke our file-scope assembly code. The constraints have been picked
- // carefully to match what the rest of the assembly code expects in input,
- // output, and clobbered registers.
+// Invoke our file-scope assembly code. The constraints have been picked
+// carefully to match what the rest of the assembly code expects in input,
+// output, and clobbered registers.
#if defined(__i386__)
intptr_t ret = nr;
asm volatile(
- "call SyscallAsm\n"
- // N.B. These are not the calling conventions normally used by the ABI.
- : "=a"(ret)
- : "0"(ret), "D"(args)
- : "cc", "esp", "memory", "ecx", "edx");
+ "call SyscallAsm\n"
+ // N.B. These are not the calling conventions normally used by the ABI.
+ : "=a"(ret)
+ : "0"(ret), "D"(args)
+ : "cc", "esp", "memory", "ecx", "edx");
#elif defined(__x86_64__)
intptr_t ret = nr;
{
- register const intptr_t *data __asm__("r12") = args;
+ register const intptr_t* data __asm__("r12") = args;
asm volatile(
- "lea -128(%%rsp), %%rsp\n" // Avoid red zone.
- "call SyscallAsm\n"
- "lea 128(%%rsp), %%rsp\n"
- // N.B. These are not the calling conventions normally used by the ABI.
- : "=a"(ret)
- : "0"(ret), "r"(data)
- : "cc", "rsp", "memory",
- "rcx", "rdi", "rsi", "rdx", "r8", "r9", "r10", "r11");
+ "lea -128(%%rsp), %%rsp\n" // Avoid red zone.
+ "call SyscallAsm\n"
+ "lea 128(%%rsp), %%rsp\n"
+ // N.B. These are not the calling conventions normally used by the ABI.
+ : "=a"(ret)
+ : "0"(ret), "r"(data)
+ : "cc",
+ "rsp",
+ "memory",
+ "rcx",
+ "rdi",
+ "rsi",
+ "rdx",
+ "r8",
+ "r9",
+ "r10",
+ "r11");
}
#elif defined(__arm__)
intptr_t ret;
{
register intptr_t inout __asm__("r0") = nr;
- register const intptr_t *data __asm__("r6") = args;
+ register const intptr_t* data __asm__("r6") = args;
asm volatile(
- "bl SyscallAsm\n"
- // N.B. These are not the calling conventions normally used by the ABI.
- : "=r"(inout)
- : "0"(inout), "r"(data)
- : "cc", "lr", "memory", "r1", "r2", "r3", "r4", "r5"
+ "bl SyscallAsm\n"
+ // N.B. These are not the calling conventions normally used by the ABI.
+ : "=r"(inout)
+ : "0"(inout), "r"(data)
+ : "cc",
+ "lr",
+ "memory",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5"
#if !defined(__thumb__)
- // In thumb mode, we cannot use "r7" as a general purpose register, as
- // it is our frame pointer. We have to manually manage and preserve it.
- // In ARM mode, we have a dedicated frame pointer register and "r7" is
- // thus available as a general purpose register. We don't preserve it,
- // but instead mark it as clobbered.
- , "r7"
+ // In thumb mode, we cannot use "r7" as a general purpose register, as
+ // it is our frame pointer. We have to manually manage and preserve
+ // it.
+ // In ARM mode, we have a dedicated frame pointer register and "r7" is
+ // thus available as a general purpose register. We don't preserve it,
+ // but instead mark it as clobbered.
+ ,
+ "r7"
#endif // !defined(__thumb__)
- );
+ );
ret = inout;
}
#else
- errno = ENOSYS;
- intptr_t ret = -1;
+#error "Unimplemented architecture"
#endif
return ret;
}
diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h
index f444d3a..57970a3 100644
--- a/sandbox/linux/seccomp-bpf/syscall.h
+++ b/sandbox/linux/seccomp-bpf/syscall.h
@@ -7,141 +7,82 @@
#include <stdint.h>
+#include "base/macros.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
-// We have to make sure that we have a single "magic" return address for
-// our system calls, which we can check from within a BPF filter. This
-// works by writing a little bit of asm() code that a) enters the kernel, and
-// that also b) can be invoked in a way that computes this return address.
-// Passing "nr" as "-1" computes the "magic" return address. Passing any
-// other value invokes the appropriate system call.
-SANDBOX_EXPORT intptr_t SandboxSyscall(int nr,
- intptr_t p0,
- intptr_t p1,
- intptr_t p2,
- intptr_t p3,
- intptr_t p4,
- intptr_t p5);
-
-// System calls can take up to six parameters. Traditionally, glibc
-// implements this property by using variadic argument lists. This works, but
-// confuses modern tools such as valgrind, because we are nominally passing
-// uninitialized data whenever we call through this function and pass less
-// than the full six arguments.
-// So, instead, we use C++'s template system to achieve a very similar
-// effect. C++ automatically sets the unused parameters to zero for us, and
-// it also does the correct type expansion (e.g. from 32bit to 64bit) where
-// necessary.
-// We have to use C-style cast operators as we want to be able to accept both
-// integer and pointer types.
-// We explicitly mark all functions as inline. This is not necessary in
-// optimized builds, where the compiler automatically figures out that it
-// can inline everything. But it makes stack traces of unoptimized builds
-// easier to read as it hides implementation details.
-#if __cplusplus >= 201103 // C++11
-
-template <class T0 = intptr_t,
- class T1 = intptr_t,
- class T2 = intptr_t,
- class T3 = intptr_t,
- class T4 = intptr_t,
- class T5 = intptr_t>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr,
- T0 p0 = 0,
- T1 p1 = 0,
- T2 p2 = 0,
- T3 p3 = 0,
- T4 p4 = 0,
- T5 p5 = 0)
- __attribute__((always_inline));
-
-template <class T0, class T1, class T2, class T3, class T4, class T5>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) {
- return SandboxSyscall(nr,
- (intptr_t)p0,
- (intptr_t)p1,
- (intptr_t)p2,
- (intptr_t)p3,
- (intptr_t)p4,
- (intptr_t)p5);
-}
-
-#else // Pre-C++11
-
-// TODO(markus): C++11 has a much more concise and readable solution for
-// expressing what we are doing here. Delete the fall-back code for older
-// compilers as soon as we have fully switched to C++11
-
-template <class T0, class T1, class T2, class T3, class T4, class T5>
-SANDBOX_EXPORT inline intptr_t
- SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
- __attribute__((always_inline));
-template <class T0, class T1, class T2, class T3, class T4, class T5>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) {
- return SandboxSyscall(nr,
- (intptr_t)p0,
- (intptr_t)p1,
- (intptr_t)p2,
- (intptr_t)p3,
- (intptr_t)p4,
- (intptr_t)p5);
-}
-
-template <class T0, class T1, class T2, class T3, class T4>
-SANDBOX_EXPORT inline intptr_t
- SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4)
- __attribute__((always_inline));
-template <class T0, class T1, class T2, class T3, class T4>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) {
- return SandboxSyscall(nr, p0, p1, p2, p3, p4, 0);
-}
-
-template <class T0, class T1, class T2, class T3>
-SANDBOX_EXPORT inline intptr_t
- SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3)
- __attribute__((always_inline));
-template <class T0, class T1, class T2, class T3>
-SANDBOX_EXPORT inline intptr_t
-SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2, T3 p3) {
- return SandboxSyscall(nr, p0, p1, p2, p3, 0, 0);
-}
-
-template <class T0, class T1, class T2>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2)
- __attribute__((always_inline));
-template <class T0, class T1, class T2>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1, T2 p2) {
- return SandboxSyscall(nr, p0, p1, p2, 0, 0, 0);
-}
-
-template <class T0, class T1>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1)
- __attribute__((always_inline));
-template <class T0, class T1>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0, T1 p1) {
- return SandboxSyscall(nr, p0, p1, 0, 0, 0, 0);
-}
-
-template <class T0>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0)
- __attribute__((always_inline));
-template <class T0>
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr, T0 p0) {
- return SandboxSyscall(nr, p0, 0, 0, 0, 0, 0);
-}
-
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr)
- __attribute__((always_inline));
-SANDBOX_EXPORT inline intptr_t SandboxSyscall(int nr) {
- return SandboxSyscall(nr, 0, 0, 0, 0, 0, 0);
-}
-
-#endif // Pre-C++11
+// This purely static class can be used to perform system calls with some
+// low-level control.
+class SANDBOX_EXPORT Syscall {
+ public:
+ // This performs system call |nr| with the arguments p0 to p5 from a constant
+ // userland address, which is for instance observable by seccomp-bpf filters.
+ // The constant userland address from which these system calls are made will
+ // be returned if |nr| is passed as -1.
+ // On error, this function will return a value between -1 and -4095 which
+ // should be interpreted as -errno.
+ static intptr_t Call(int nr,
+ intptr_t p0,
+ intptr_t p1,
+ intptr_t p2,
+ intptr_t p3,
+ intptr_t p4,
+ intptr_t p5);
+
+ // System calls can take up to six parameters. Traditionally, glibc
+ // implements this property by using variadic argument lists. This works, but
+ // confuses modern tools such as valgrind, because we are nominally passing
+ // uninitialized data whenever we call through this function and pass less
+ // than the full six arguments.
+ // So, instead, we use C++'s template system to achieve a very similar
+ // effect. C++ automatically sets the unused parameters to zero for us, and
+ // it also does the correct type expansion (e.g. from 32bit to 64bit) where
+ // necessary.
+ // We have to use C-style cast operators as we want to be able to accept both
+ // integer and pointer types.
+ template <class T0, class T1, class T2, class T3, class T4, class T5>
+ static inline intptr_t
+ Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) {
+ return Call(nr,
+ (intptr_t)p0,
+ (intptr_t)p1,
+ (intptr_t)p2,
+ (intptr_t)p3,
+ (intptr_t)p4,
+ (intptr_t)p5);
+ }
+
+ template <class T0, class T1, class T2, class T3, class T4>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) {
+ return Call(nr, p0, p1, p2, p3, p4, 0);
+ }
+
+ template <class T0, class T1, class T2, class T3>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2, T3 p3) {
+ return Call(nr, p0, p1, p2, p3, 0, 0);
+ }
+
+ template <class T0, class T1, class T2>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1, T2 p2) {
+ return Call(nr, p0, p1, p2, 0, 0, 0);
+ }
+
+ template <class T0, class T1>
+ static inline intptr_t Call(int nr, T0 p0, T1 p1) {
+ return Call(nr, p0, p1, 0, 0, 0, 0);
+ }
+
+ template <class T0>
+ static inline intptr_t Call(int nr, T0 p0) {
+ return Call(nr, p0, 0, 0, 0, 0, 0);
+ }
+
+ static inline intptr_t Call(int nr) { return Call(nr, 0, 0, 0, 0, 0, 0); }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Syscall);
+};
} // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index bdeee4f..80b5079 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/posix/eintr_wrapper.h"
+#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
@@ -31,24 +32,25 @@ const int kMMapNr = __NR_mmap;
#endif
TEST(Syscall, WellKnownEntryPoint) {
-// Test that SandboxSyscall(-1) is handled specially. Don't do this on ARM,
+// 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
// are still testing ARM code in the next set of tests.
#if !defined(__arm__)
- EXPECT_NE(SandboxSyscall(-1), syscall(-1));
+ EXPECT_NE(Syscall::Call(-1), syscall(-1));
#endif
-// If possible, test that SandboxSyscall(-1) returns the address right after
+// If possible, test that Syscall::Call(-1) returns the address right
+// after
// a kernel entry point.
#if defined(__i386__)
- EXPECT_EQ(0x80CDu, ((uint16_t*)SandboxSyscall(-1))[-1]); // INT 0x80
+ EXPECT_EQ(0x80CDu, ((uint16_t*)Syscall::Call(-1))[-1]); // INT 0x80
#elif defined(__x86_64__)
- EXPECT_EQ(0x050Fu, ((uint16_t*)SandboxSyscall(-1))[-1]); // SYSCALL
+ EXPECT_EQ(0x050Fu, ((uint16_t*)Syscall::Call(-1))[-1]); // SYSCALL
#elif defined(__arm__)
#if defined(__thumb__)
- EXPECT_EQ(0xDF00u, ((uint16_t*)SandboxSyscall(-1))[-1]); // SWI 0
+ EXPECT_EQ(0xDF00u, ((uint16_t*)Syscall::Call(-1))[-1]); // SWI 0
#else
- EXPECT_EQ(0xEF000000u, ((uint32_t*)SandboxSyscall(-1))[-1]); // SVC 0
+ EXPECT_EQ(0xEF000000u, ((uint32_t*)Syscall::Call(-1))[-1]); // SVC 0
#endif
#else
#warning Incomplete test case; need port for target platform
@@ -57,17 +59,25 @@ TEST(Syscall, WellKnownEntryPoint) {
TEST(Syscall, TrivialSyscallNoArgs) {
// Test that we can do basic system calls
- EXPECT_EQ(SandboxSyscall(__NR_getpid), syscall(__NR_getpid));
+ EXPECT_EQ(Syscall::Call(__NR_getpid), syscall(__NR_getpid));
}
TEST(Syscall, TrivialSyscallOneArg) {
int new_fd;
// Duplicate standard error and close it.
- ASSERT_GE(new_fd = SandboxSyscall(__NR_dup, 2), 0);
- int close_return_value = IGNORE_EINTR(SandboxSyscall(__NR_close, new_fd));
+ ASSERT_GE(new_fd = Syscall::Call(__NR_dup, 2), 0);
+ int close_return_value = IGNORE_EINTR(Syscall::Call(__NR_close, new_fd));
ASSERT_EQ(close_return_value, 0);
}
+TEST(Syscall, TrivialFailingSyscall) {
+ errno = -42;
+ int ret = Syscall::Call(__NR_dup, -1);
+ ASSERT_EQ(-EBADF, ret);
+ // Verify that Syscall::Call does not touch errno.
+ ASSERT_EQ(-42, errno);
+}
+
// SIGSYS trap handler that will be called on __NR_uname.
intptr_t CopySyscallArgsToAux(const struct arch_seccomp_data& args, void* aux) {
// |aux| is our BPF_AUX pointer.
@@ -91,7 +101,8 @@ ErrorCode CopyAllArgsOnUnamePolicy(SandboxBPF* sandbox,
}
}
-// We are testing SandboxSyscall() by making use of a BPF filter that allows us
+// We are testing Syscall::Call() by making use of a BPF filter that
+// allows us
// to inspect the system call arguments that the kernel saw.
BPF_TEST(Syscall,
SyntheticSixArgs,
@@ -109,13 +120,13 @@ BPF_TEST(Syscall,
// We could use pretty much any system call we don't need here. uname() is
// nice because it doesn't have any dangerous side effects.
- BPF_ASSERT(SandboxSyscall(__NR_uname,
- syscall_args[0],
- syscall_args[1],
- syscall_args[2],
- syscall_args[3],
- syscall_args[4],
- syscall_args[5]) == -ENOMEM);
+ BPF_ASSERT(Syscall::Call(__NR_uname,
+ syscall_args[0],
+ syscall_args[1],
+ syscall_args[2],
+ syscall_args[3],
+ syscall_args[4],
+ syscall_args[5]) == -ENOMEM);
// We expect the trap handler to have copied the 6 arguments.
BPF_ASSERT(BPF_AUX->size() == 6);
@@ -133,69 +144,69 @@ BPF_TEST(Syscall,
TEST(Syscall, ComplexSyscallSixArgs) {
int fd;
- ASSERT_LE(0, fd = SandboxSyscall(__NR_open, "/dev/null", O_RDWR, 0L));
+ ASSERT_LE(0, fd = Syscall::Call(__NR_open, "/dev/null", O_RDWR, 0L));
// Use mmap() to allocate some read-only memory
char* addr0;
- ASSERT_NE((char*)NULL,
- addr0 = reinterpret_cast<char*>(
- SandboxSyscall(kMMapNr,
- (void*)NULL,
- 4096,
- PROT_READ,
- MAP_PRIVATE | MAP_ANONYMOUS,
- fd,
- 0L)));
+ ASSERT_NE(
+ (char*)NULL,
+ addr0 = reinterpret_cast<char*>(Syscall::Call(kMMapNr,
+ (void*)NULL,
+ 4096,
+ PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ fd,
+ 0L)));
// Try to replace the existing mapping with a read-write mapping
char* addr1;
ASSERT_EQ(addr0,
addr1 = reinterpret_cast<char*>(
- SandboxSyscall(kMMapNr,
- addr0,
- 4096L,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
- fd,
- 0L)));
+ Syscall::Call(kMMapNr,
+ addr0,
+ 4096L,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+ fd,
+ 0L)));
++*addr1; // This should not seg fault
// Clean up
- EXPECT_EQ(0, SandboxSyscall(__NR_munmap, addr1, 4096L));
- EXPECT_EQ(0, IGNORE_EINTR(SandboxSyscall(__NR_close, fd)));
+ EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr1, 4096L));
+ EXPECT_EQ(0, IGNORE_EINTR(Syscall::Call(__NR_close, fd)));
// Check that the offset argument (i.e. the sixth argument) is processed
// correctly.
- ASSERT_GE(fd = SandboxSyscall(__NR_open, "/proc/self/exe", O_RDONLY, 0L), 0);
+ ASSERT_GE(fd = Syscall::Call(__NR_open, "/proc/self/exe", O_RDONLY, 0L), 0);
char* addr2, *addr3;
ASSERT_NE((char*)NULL,
- addr2 = reinterpret_cast<char*>(SandboxSyscall(
+ addr2 = reinterpret_cast<char*>(Syscall::Call(
kMMapNr, (void*)NULL, 8192L, PROT_READ, MAP_PRIVATE, fd, 0L)));
ASSERT_NE((char*)NULL,
- addr3 = reinterpret_cast<char*>(SandboxSyscall(kMMapNr,
- (void*)NULL,
- 4096L,
- PROT_READ,
- MAP_PRIVATE,
- fd,
+ addr3 = reinterpret_cast<char*>(Syscall::Call(kMMapNr,
+ (void*)NULL,
+ 4096L,
+ PROT_READ,
+ MAP_PRIVATE,
+ fd,
#if defined(__NR_mmap2)
- 1L
+ 1L
#else
- 4096L
+ 4096L
#endif
- )));
+ )));
EXPECT_EQ(0, memcmp(addr2 + 4096, addr3, 4096));
// Just to be absolutely on the safe side, also verify that the file
// contents matches what we are getting from a read() operation.
char buf[8192];
- EXPECT_EQ(8192, SandboxSyscall(__NR_read, fd, buf, 8192L));
+ EXPECT_EQ(8192, Syscall::Call(__NR_read, fd, buf, 8192L));
EXPECT_EQ(0, memcmp(addr2, buf, 8192));
// Clean up
- EXPECT_EQ(0, SandboxSyscall(__NR_munmap, addr2, 8192L));
- EXPECT_EQ(0, SandboxSyscall(__NR_munmap, addr3, 4096L));
- EXPECT_EQ(0, IGNORE_EINTR(SandboxSyscall(__NR_close, fd)));
+ EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr2, 8192L));
+ EXPECT_EQ(0, Syscall::Call(__NR_munmap, addr3, 4096L));
+ EXPECT_EQ(0, IGNORE_EINTR(Syscall::Call(__NR_close, fd)));
}
} // namespace
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index f8b64c9..4c42111 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -168,13 +168,13 @@ void Trap::SigSys(int nr, siginfo_t* info, void* void_context) {
if (sigsys.nr == __NR_clone) {
RAW_SANDBOX_DIE("Cannot call clone() from an UnsafeTrap() handler.");
}
- rc = SandboxSyscall(sigsys.nr,
- SECCOMP_PARM1(ctx),
- SECCOMP_PARM2(ctx),
- SECCOMP_PARM3(ctx),
- SECCOMP_PARM4(ctx),
- SECCOMP_PARM5(ctx),
- SECCOMP_PARM6(ctx));
+ rc = Syscall::Call(sigsys.nr,
+ SECCOMP_PARM1(ctx),
+ SECCOMP_PARM2(ctx),
+ SECCOMP_PARM3(ctx),
+ SECCOMP_PARM4(ctx),
+ SECCOMP_PARM5(ctx),
+ SECCOMP_PARM6(ctx));
} else {
const ErrorCode& err = trap_array_[info->si_errno - 1];
if (!err.safe_) {
@@ -227,7 +227,7 @@ ErrorCode Trap::MakeTrapImpl(TrapFnc fnc, const void* aux, bool safe) {
// we never return an ErrorCode that is marked as "unsafe". This also
// means, the BPF compiler will never emit code that allow unsafe system
// calls to by-pass the filter (because they use the magic return address
- // from SandboxSyscall(-1)).
+ // from Syscall::Call(-1)).
// This SANDBOX_DIE() can optionally be removed. It won't break security,
// but it might make error messages from the BPF compiler a little harder