diff options
author | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-13 12:59:59 +0000 |
---|---|---|
committer | jln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-13 12:59:59 +0000 |
commit | a24c66d2a9ac204ada9ad3a636256a2ed8c4ad28 (patch) | |
tree | f4a0279e8a1f3aba5bc2d0f4dc43570255901a76 /sandbox | |
parent | d87e618b08ffd716085acb367c3837cb1ac90ef5 (diff) | |
download | chromium_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.cc | 8 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf.cc | 21 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf.h | 1 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc | 44 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/syscall.cc | 391 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/syscall.h | 203 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/syscall_unittest.cc | 115 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/trap.cc | 16 |
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 |