diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-20 12:30:35 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-20 12:30:35 +0000 |
commit | 4a72e663d062df7ba73d97a25ae3e397b65f8aea (patch) | |
tree | a1b57b5b4bffcc03a16c41e3e453b955fff5c769 /sandbox | |
parent | 933b7483adef1676e75b88183d0d8768063fe839 (diff) | |
download | chromium_src-4a72e663d062df7ba73d97a25ae3e397b65f8aea.zip chromium_src-4a72e663d062df7ba73d97a25ae3e397b65f8aea.tar.gz chromium_src-4a72e663d062df7ba73d97a25ae3e397b65f8aea.tar.bz2 |
Revert 174135
> SECCOMP-BPF: Added support for checking system call arguments against bit masks.
>
>
> BUG=130662
> TEST=sandbox_linux_unittests
>
>
> Review URL: https://chromiumcodereview.appspot.com/11613016
Tests fail on Linux Precise bot: http://build.chromium.org/p/chromium.linux/buildstatus?builder=Linux%20Precise%20%28dbg%29&number=410
TBR=markus@chromium.org
Review URL: https://codereview.chromium.org/11618035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@174147 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r-- | sandbox/linux/seccomp-bpf/codegen.cc | 15 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/errorcode.h | 47 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf.cc | 118 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf.h | 7 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc | 478 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/verifier.cc | 104 | ||||
-rw-r--r-- | sandbox/linux/seccomp-bpf/verifier.h | 2 |
7 files changed, 19 insertions, 752 deletions
diff --git a/sandbox/linux/seccomp-bpf/codegen.cc b/sandbox/linux/seccomp-bpf/codegen.cc index 4fab5c8..649793c 100644 --- a/sandbox/linux/seccomp-bpf/codegen.cc +++ b/sandbox/linux/seccomp-bpf/codegen.cc @@ -79,21 +79,6 @@ void CodeGen::PrintProgram(const Sandbox::Program& program) { case BPF_RET: fprintf(stderr, "RET 0x%x\n", iter->k); break; - case BPF_ALU: - fprintf(stderr, BPF_OP(iter->code) == BPF_NEG - ? "A := -A\n" : "A := A %s 0x%x\n", - BPF_OP(iter->code) == BPF_ADD ? "+" : - BPF_OP(iter->code) == BPF_SUB ? "-" : - BPF_OP(iter->code) == BPF_MUL ? "*" : - BPF_OP(iter->code) == BPF_DIV ? "/" : - BPF_OP(iter->code) == BPF_MOD ? "%" : - BPF_OP(iter->code) == BPF_OR ? "|" : - BPF_OP(iter->code) == BPF_XOR ? "^" : - BPF_OP(iter->code) == BPF_AND ? "&" : - BPF_OP(iter->code) == BPF_LSH ? "<<" : - BPF_OP(iter->code) == BPF_RSH ? ">>" : "???", - (int)iter->k); - break; default: fprintf(stderr, "???\n"); break; diff --git a/sandbox/linux/seccomp-bpf/errorcode.h b/sandbox/linux/seccomp-bpf/errorcode.h index 67890c6..d2661db 100644 --- a/sandbox/linux/seccomp-bpf/errorcode.h +++ b/sandbox/linux/seccomp-bpf/errorcode.h @@ -20,17 +20,11 @@ struct arch_seccomp_data; class ErrorCode { public: enum { - // Allow this system call. The value of ERR_ALLOWED is pretty much - // completely arbitrary. But we want to pick it so that is is unlikely - // to be passed in accidentally, when the user intended to return an - // "errno" (see below) value instead. - ERR_ALLOWED = 0x04000000, + // Allow this system call. + ERR_ALLOWED = 0x0000, // Deny the system call with a particular "errno" value. - // N.B.: It is also possible to return "0" here. That would normally - // indicate success, but it won't actually run the system call. - // This is very different from return ERR_ALLOWED. - ERR_MIN_ERRNO = 0, + ERR_MIN_ERRNO = 1, ERR_MAX_ERRNO = 4095, // This code should never be used directly, it is used internally only. @@ -48,42 +42,11 @@ class ErrorCode { typedef intptr_t (*TrapFnc)(const struct arch_seccomp_data& args, void *aux); enum ArgType { - // A conditional test should operate on the 32bit part of the system call - // argument. - // On 64bit architectures, this verifies that the caller did not actually - // pass in a 64bit value. If they did, that will be interpreted as an - // attempt at breaking the sandbox and results in the program getting - // terminated. - // In other words, only perform a 32bit test, if you are sure this - // particular system call would never legitimately take a 64bit argument. - TP_32BIT, - - // A conditional test should operate on 64bit arguments. It is harmless - // to perform a 64bit test on a 32bit system, as the top 32 bits of all - // arguments will always be zero. - TP_64BIT, + TP_32BIT, TP_64BIT, }; enum Operation { - // Test whether the system call argument is equal to the operand. - OP_EQUAL, - - // Test whether the system call argument is greater (or equal) to the - // operand. Please note that all tests always operate on unsigned - // values. You can generally emulate signed tests, if that's what you - // need. - // TODO(markus): Check whether we should automatically emulate signed - // operations. - OP_GREATER_UNSIGNED, OP_GREATER_EQUAL_UNSIGNED, - - // Tests a system call argument against a bit mask. - // The "ALL_BITS" variant performs this test: "arg & mask == mask" - // This implies that a mask of zero always results in a passing test. - // The "ANY_BITS" variant performs this test: "arg & mask != 0" - // This implies that a mask of zero always results in a failing test. - OP_HAS_ALL_BITS, OP_HAS_ANY_BITS, - - // Total number of operations. + OP_EQUAL, OP_GREATER, OP_GREATER_EQUAL, OP_HAS_BITS, OP_NUM_OPS, }; diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc index 130845f..366706f 100644 --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc @@ -60,17 +60,6 @@ void SetIsInSigHandler() { sigprocmask(SIG_BLOCK, &mask, NULL); } -template<class T> int popcount(T x); -template<> int popcount<unsigned int>(unsigned int x) { - return __builtin_popcount(x); -} -template<> int popcount<unsigned long>(unsigned long x) { - return __builtin_popcountl(x); -} -template<> int popcount<unsigned long long>(unsigned long long x) { - return __builtin_popcountll(x); -} - } // namespace // The kernel gives us a sandbox, we turn it into a playground :-) @@ -759,114 +748,13 @@ Instruction *Sandbox::CondExpression(CodeGen *gen, const ErrorCode& cond) { if (cond.width_ == ErrorCode::TP_64BIT) { msb_tail = gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, static_cast<uint32_t>(cond.value_ >> 32), - lsb_head, + NULL, RetExpression(gen, *cond.failed_)); gen->JoinInstructions(msb_head, msb_tail); } break; - case ErrorCode::OP_HAS_ALL_BITS: - // Check the bits in the LSB half of the system call argument. Our - // OP_HAS_ALL_BITS operator passed, iff all of the bits are set. This is - // different from the kernel's BPF_JSET operation which passes, if any of - // the bits are set. - // Of course, if there is only a single set bit (or none at all), then - // things get easier. - { - uint32_t lsb_bits = static_cast<uint32_t>(cond.value_); - int lsb_bit_count = popcount(lsb_bits); - if (lsb_bit_count == 0) { - // No bits are set in the LSB half. The test will always pass. - lsb_head = RetExpression(gen, *cond.passed_); - lsb_tail = NULL; - } else if (lsb_bit_count == 1) { - // Exactly one bit is set in the LSB half. We can use the BPF_JSET - // operator. - lsb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, - lsb_bits, - RetExpression(gen, *cond.passed_), - RetExpression(gen, *cond.failed_)); - gen->JoinInstructions(lsb_head, lsb_tail); - } else { - // More than one bit is set in the LSB half. We need to combine - // BPF_AND and BPF_JEQ to test whether all of these bits are in fact - // set in the system call argument. - gen->JoinInstructions(lsb_head, - gen->MakeInstruction(BPF_ALU+BPF_AND+BPF_K, - lsb_bits, - lsb_tail = gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, - lsb_bits, - RetExpression(gen, *cond.passed_), - RetExpression(gen, *cond.failed_)))); - } - } - - // If we are looking at a 64bit argument, we need to also check the bits - // in the MSB half of the system call argument. - if (cond.width_ == ErrorCode::TP_64BIT) { - uint32_t msb_bits = static_cast<uint32_t>(cond.value_ >> 32); - int msb_bit_count = popcount(msb_bits); - if (msb_bit_count == 0) { - // No bits are set in the MSB half. The test will always pass. - msb_head = lsb_head; - } else if (msb_bit_count == 1) { - // Exactly one bit is set in the MSB half. We can use the BPF_JSET - // operator. - msb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, - msb_bits, - lsb_head, - RetExpression(gen, *cond.failed_)); - gen->JoinInstructions(msb_head, msb_tail); - } else { - // More than one bit is set in the MSB half. We need to combine - // BPF_AND and BPF_JEQ to test whether all of these bits are in fact - // set in the system call argument. - gen->JoinInstructions(msb_head, - gen->MakeInstruction(BPF_ALU+BPF_AND+BPF_K, - msb_bits, - gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, - msb_bits, - lsb_head, - RetExpression(gen, *cond.failed_)))); - } - } - break; - case ErrorCode::OP_HAS_ANY_BITS: - // Check the bits in the LSB half of the system call argument. Our - // OP_HAS_ANY_BITS operator passed, iff any of the bits are set. This maps - // nicely to the kernel's BPF_JSET operation. - { - uint32_t lsb_bits = static_cast<uint32_t>(cond.value_); - if (!lsb_bits) { - // No bits are set in the LSB half. The test will always fail. - lsb_head = RetExpression(gen, *cond.failed_); - lsb_tail = NULL; - } else { - lsb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, - lsb_bits, - RetExpression(gen, *cond.passed_), - RetExpression(gen, *cond.failed_)); - gen->JoinInstructions(lsb_head, lsb_tail); - } - } - - // If we are looking at a 64bit argument, we need to also check the bits - // in the MSB half of the system call argument. - if (cond.width_ == ErrorCode::TP_64BIT) { - uint32_t msb_bits = static_cast<uint32_t>(cond.value_ >> 32); - if (!msb_bits) { - // No bits are set in the MSB half. The test will always fail. - msb_head = lsb_head; - } else { - msb_tail = gen->MakeInstruction(BPF_JMP+BPF_JSET+BPF_K, - msb_bits, - RetExpression(gen, *cond.passed_), - lsb_head); - gen->JoinInstructions(msb_head, msb_tail); - } - } - break; default: - // TODO(markus): Need to add support for OP_GREATER + // TODO(markus): We can only check for equality so far. SANDBOX_DIE("Not implemented"); break; } @@ -897,6 +785,8 @@ Instruction *Sandbox::CondExpression(CodeGen *gen, const ErrorCode& cond) { gen->MakeInstruction(BPF_JMP+BPF_JEQ+BPF_K, 0, lsb_head, invalid_64bit)); + } else { + gen->JoinInstructions(msb_tail, lsb_head); } return msb_head; diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/sandbox/linux/seccomp-bpf/sandbox_bpf.h index 1142ce5..aee03fa 100644 --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.h +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.h @@ -97,13 +97,6 @@ #define IPC_64 0x0100 #endif -#ifndef BPF_MOD -#define BPF_MOD 0x90 -#endif -#ifndef BPF_XOR -#define BPF_XOR 0xA0 -#endif - // In order to build will older tool chains, we currently have to avoid // including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on // our own definitions of the seccomp kernel ABI. diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc index 015e2d2..90ec8ff 100644 --- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <errno.h> -#include <sys/prctl.h> #include <sys/syscall.h> #include <sys/utsname.h> @@ -18,10 +16,7 @@ #include "testing/gtest/include/gtest/gtest.h" // Workaround for Android's prctl.h file. -#ifndef PR_GET_ENDIAN -#define PR_GET_ENDIAN 19 -#endif -#ifndef PR_CAPBSET_READ +#if !defined(PR_CAPBSET_READ) #define PR_CAPBSET_READ 23 #define PR_CAPBSET_DROP 24 #endif @@ -185,51 +180,6 @@ BPF_TEST(SandboxBpf, BasicBlacklistWithSigsys, BPF_ASSERT(BPF_AUX == kExpectedReturnValue); } -// A simple test that verifies we can return arbitrary errno values. - -ErrorCode ErrnoTestPolicy(int sysno, void *) { - if (!Sandbox::IsValidSyscallNumber(sysno)) { - // FIXME: we should really not have to do that in a trivial policy - return ErrorCode(ENOSYS); - } - - switch (sysno) { - case __NR_dup2: - // Pretend that dup2() worked, but don't actually do anything. - return ErrorCode(0); - case __NR_setuid: - // Return errno = 1 - return ErrorCode(1); - case __NR_setgid: - // Return maximum errno value (typically 4095). - return ErrorCode(ErrorCode::ERR_MAX_ERRNO); - default: - return ErrorCode(ErrorCode::ERR_ALLOWED); - } -} - -BPF_TEST(SandboxBpf, ErrnoTest, ErrnoTestPolicy) { - // Verify that dup2() returns success, but doesn't actually run. - int fds[4]; - BPF_ASSERT(pipe(fds) == 0); - BPF_ASSERT(pipe(fds+2) == 0); - BPF_ASSERT(dup2(fds[2], fds[0]) == 0); - char buf[1] = { }; - BPF_ASSERT(write(fds[1], "\x55", 1) == 1); - BPF_ASSERT(write(fds[3], "\xAA", 1) == 1); - BPF_ASSERT(read(fds[0], buf, 1) == 1); - - // If dup2() executed, we will read \xAA, but it dup2() has been turned - // into a no-op by our policy, then we will read \x55. - BPF_ASSERT(buf[0] == '\x55'); - - // Verify that we can return the minimum and maximum errno values. - BPF_ASSERT(setuid(0) == -1); - BPF_ASSERT(errno == 1); - BPF_ASSERT(setgid(0) == -1); - BPF_ASSERT(errno == ErrorCode::ERR_MAX_ERRNO); -} - // A more complex, but synthetic policy. This tests the correctness of the BPF // program by iterating through all syscalls and checking for an errno that // depends on the syscall number. Unlike the Verifier, this exercises the BPF @@ -640,54 +590,6 @@ BPF_TEST(SandboxBpf, UseOpenBroker, DenyOpenPolicy, BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0); } -// Simple test demonstrating how to use Sandbox::Cond() - -ErrorCode SimpleCondTestPolicy(int sysno, void *) { - if (!Sandbox::IsValidSyscallNumber(sysno)) { - // FIXME: we should really not have to do that in a trivial policy - return ErrorCode(ENOSYS); - } - - // 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. - switch (sysno) { - case __NR_open: - // 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, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, - O_ACCMODE /* 0x3 */, - ErrorCode(EROFS), - ErrorCode(ErrorCode::ERR_ALLOWED)); - case __NR_prctl: - // Allow prctl(PR_SET_DUMPABLE) and prctl(PR_GET_DUMPABLE), but - // disallow everything else. - return Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, - PR_SET_DUMPABLE, - ErrorCode(ErrorCode::ERR_ALLOWED), - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, - PR_GET_DUMPABLE, - ErrorCode(ErrorCode::ERR_ALLOWED), - ErrorCode(ENOMEM))); - default: - return ErrorCode(ErrorCode::ERR_ALLOWED); - } -} - -BPF_TEST(SandboxBpf, SimpleCondTest, SimpleCondTestPolicy) { - int fd; - BPF_ASSERT((fd = open("/proc/self/comm", O_RDWR)) == -1); - BPF_ASSERT(errno == EROFS); - BPF_ASSERT((fd = open("/proc/self/comm", O_RDONLY)) >= 0); - close(fd); - - int ret; - BPF_ASSERT((ret = prctl(PR_GET_DUMPABLE)) >= 0); - BPF_ASSERT(prctl(PR_SET_DUMPABLE, 1-ret) == 0); - BPF_ASSERT(prctl(PR_GET_ENDIAN, &ret) == -1); - BPF_ASSERT(errno == ENOMEM); -} - // This test exercises the Sandbox::Cond() method by building a complex // tree of conditional equality operations. It then makes system calls and // verifies that they return the values that we expected from our BPF @@ -1006,7 +908,7 @@ ErrorCode EqualityArgumentWidthPolicy(int sysno, void *) { Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0x55555555, ErrorCode(1), ErrorCode(2)), Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_EQUAL, - 0x55555555AAAAAAAAULL, ErrorCode(1), ErrorCode(2))); + 0x55555555AAAAAAAAull, ErrorCode(1), ErrorCode(2))); } else { return ErrorCode(ErrorCode::ERR_ALLOWED); } @@ -1019,10 +921,10 @@ BPF_TEST(SandboxBpf, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { // 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(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); #endif } @@ -1033,7 +935,7 @@ BPF_TEST(SandboxBpf, EqualityArgumentWidth, EqualityArgumentWidthPolicy) { BPF_DEATH_TEST(SandboxBpf, EqualityArgumentUnallowed64bit, DEATH_MESSAGE("Unexpected 64bit argument detected"), EqualityArgumentWidthPolicy) { - SandboxSyscall(__NR_uname, 0, 0x5555555555555555ULL); + SandboxSyscall(__NR_uname, 0, 0x5555555555555555ull); } #endif @@ -1053,7 +955,7 @@ BPF_TEST(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(SandboxSyscall(__NR_uname, -1ll) == -1); } #if __SIZEOF_POINTER__ > 4 @@ -1063,370 +965,8 @@ BPF_DEATH_TEST(SandboxBpf, EqualityWithNegative64bitArguments, // 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(SandboxSyscall(__NR_uname, 0xFFFFFFFF00000000ll) == -1); } #endif -ErrorCode AllBitTestPolicy(int sysno, void *) { - // Test the OP_HAS_ALL_BITS conditional test operator with a couple of - // different bitmasks. We try to find bitmasks that could conceivably - // touch corner cases. - // For all of these tests, we override the uname(). We can make use with - // a single system call number, as we use the first system call argument to - // select the different bit masks that we want to test against. - if (!Sandbox::IsValidSyscallNumber(sysno)) { - // FIXME: we should really not have to do that in a trivial policy - return ErrorCode(ENOSYS); - } else if (sysno == __NR_uname) { - return Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x0, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x1, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 2, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x3, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 3, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x80000000, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 4, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x0, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 5, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x1, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 6, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x3, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 7, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x80000000, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 8, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x100000000ULL, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 9, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x300000000ULL, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 10, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ALL_BITS, - 0x100000001ULL, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Kill("Invalid test case number")))))))))))); - - } else { - return ErrorCode(ErrorCode::ERR_ALLOWED); - } -} - -BPF_TEST(SandboxBpf, AllBitTests, AllBitTestPolicy) { - // Our uname() system call returns ErrorCode(1) for success and - // ErrorCode(0) for failure. SandboxSyscall() turns this into an - // exit code of -1 or 0. This is compatible with traditional - // C-style boolean test values. - - // 32bit test: all of 0x0 (should always be true) - BPF_ASSERT( SandboxSyscall(__NR_uname, 0, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 0, 1)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 0, 3)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 0, 0xFFFFFFFFU)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 0, -1LL)); - - // 32bit test: all of 0x1 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 1, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 1, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 1, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 1, 3)); - - // 32bit test: all of 0x3 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 2, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 2, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 2, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 2, 3)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 2, 7)); - - // 32bit test: all of 0x80000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 3, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 3, 0x40000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 3, 0x80000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 3, 0xC0000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 3,-0x80000000LL)); - - // 64bit test: all of 0x0 (should always be true) - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, 1)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, 3)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, 0xFFFFFFFFU)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, 0x100000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, 0x300000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, 0x8000000000000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 4, -1LL)); - - // 64bit test: all of 0x1 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 3)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 0x100000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 0x100000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 0x100000002LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 0x100000003LL)); - - // 64bit test: all of 0x3 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 3)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 7)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 0x100000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 0x100000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 0x100000002LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 0x100000003LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 0x100000007LL)); - - // 64bit test: all of 0x80000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0x40000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0x80000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0xC0000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7,-0x80000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0x100000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0x140000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0x180000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0x1C0000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7,-0x180000000LL)); - - // 64bit test: all of 0x100000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x000000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x100000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x200000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x300000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x000000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x100000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x200000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x300000001LL)); - - // 64bit test: all of 0x300000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x000000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x100000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x200000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x300000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x700000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x000000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x100000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x200000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x300000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x700000001LL)); - - // 64bit test: all of 0x100000001 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 10, 0x000000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 10, 0x000000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 10, 0x100000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 10, 0x100000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 10, 0xFFFFFFFFU)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 10, -1L)); -} - -ErrorCode AnyBitTestPolicy(int sysno, void *) { - // Test the OP_HAS_ANY_BITS conditional test operator with a couple of - // different bitmasks. We try to find bitmasks that could conceivably - // touch corner cases. - // For all of these tests, we override the uname(). We can make use with - // a single system call number, as we use the first system call argument to - // select the different bit masks that we want to test against. - if (!Sandbox::IsValidSyscallNumber(sysno)) { - // FIXME: we should really not have to do that in a trivial policy - return ErrorCode(ENOSYS); - } else if (sysno == __NR_uname) { - return Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 0, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x0, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 1, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x1, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 2, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x3, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 3, - Sandbox::Cond(1, ErrorCode::TP_32BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x80000000, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 4, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x0, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 5, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x1, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 6, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x3, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 7, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x80000000, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 8, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x100000000ULL, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 9, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x300000000ULL, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, 10, - Sandbox::Cond(1, ErrorCode::TP_64BIT, ErrorCode::OP_HAS_ANY_BITS, - 0x100000001ULL, - ErrorCode(1), ErrorCode(0)), - - Sandbox::Kill("Invalid test case number")))))))))))); - - } else { - return ErrorCode(ErrorCode::ERR_ALLOWED); - } -} - -BPF_TEST(SandboxBpf, AnyBitTests, AnyBitTestPolicy) { - // Our uname() system call returns ErrorCode(1) for success and - // ErrorCode(0) for failure. SandboxSyscall() turns this into an - // exit code of -1 or 0. This is compatible with traditional - // C-style boolean test values. - - // 32bit test: any of 0x0 (should always be false) - BPF_ASSERT(!SandboxSyscall(__NR_uname, 0, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 0, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 0, 3)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 0, 0xFFFFFFFFU)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 0, -1LL)); - - // 32bit test: any of 0x1 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 1, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 1, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 1, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 1, 3)); - - // 32bit test: any of 0x3 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 2, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 2, 1)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 2, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 2, 3)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 2, 7)); - - // 32bit test: any of 0x80000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 3, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 3, 0x40000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 3, 0x80000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 3, 0xC0000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 3,-0x80000000LL)); - - // 64bit test: any of 0x0 (should always be false) - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, 3)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, 0xFFFFFFFFU)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, 0x100000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, 0x300000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, 0x8000000000000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 4, -1LL)); - - // 64bit test: any of 0x1 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 1)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 3)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 0x100000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 0x100000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 5, 0x100000002LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 5, 0x100000003LL)); - - // 64bit test: any of 0x3 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 0)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 1)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 2)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 3)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 7)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 6, 0x100000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 0x100000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 0x100000002LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 0x100000003LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 6, 0x100000007LL)); - - // 64bit test: any of 0x80000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0x40000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0x80000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0xC0000000U)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7,-0x80000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0x100000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 7, 0x140000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0x180000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7, 0x1C0000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 7,-0x180000000LL)); - - // 64bit test: any of 0x100000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x000000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x100000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x200000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x300000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x000000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x100000001LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 8, 0x200000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 8, 0x300000001LL)); - - // 64bit test: any of 0x300000000 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x000000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x100000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x200000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x300000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x700000000LL)); - BPF_ASSERT(!SandboxSyscall(__NR_uname, 9, 0x000000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x100000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x200000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x300000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 9, 0x700000001LL)); - - // 64bit test: any of 0x100000001 - BPF_ASSERT(!SandboxSyscall(__NR_uname, 10, 0x000000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 10, 0x000000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 10, 0x100000000LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 10, 0x100000001LL)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 10, 0xFFFFFFFFU)); - BPF_ASSERT( SandboxSyscall(__NR_uname, 10, -1L)); -} - } // namespace diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/seccomp-bpf/verifier.cc index 0403e1b..1c99619 100644 --- a/sandbox/linux/seccomp-bpf/verifier.cc +++ b/sandbox/linux/seccomp-bpf/verifier.cc @@ -112,41 +112,7 @@ bool Verifier::VerifyErrorCode(const std::vector<struct sock_filter>& program, } } break; - case ErrorCode::OP_HAS_ALL_BITS: - case ErrorCode::OP_HAS_ANY_BITS: - // A comprehensive test of bit values is difficult and potentially rather - // time-expensive. We avoid doing so at run-time and instead rely on the - // unittest for full testing. The test that we have here covers just the - // common cases. We test against the bitmask itself, all zeros and all - // ones. - { - // Testing "any" bits against a zero mask is always false. So, there - // are some cases, where we expect tests to take the "failed_" branch - // even though this is a test that normally should take "passed_". - const ErrorCode& passed = - !code.value_ && code.op_ == ErrorCode::OP_HAS_ANY_BITS - ? *code.failed_ : *code.passed_; - // Similary, testing for "all" bits in a zero mask is always true. So, - // some cases pass despite them normally failing. - const ErrorCode& failed = - !code.value_ && code.op_ == ErrorCode::OP_HAS_ALL_BITS - ? *code.passed_ : *code.failed_; - - data->args[code.argno_] = code.value_; - if (!VerifyErrorCode(program, data, passed, err)) { - return false; - } - data->args[code.argno_] = -1LL; - if (!VerifyErrorCode(program, data, passed, err)) { - return false; - } - data->args[code.argno_] = 0; - if (!VerifyErrorCode(program, data, failed, err)) { - return false; - } - } - break; - default: // TODO(markus): Need to add support for OP_GREATER + default: // TODO(markus): We can only check for equality so far. *err = "Unsupported operation in conditional error code"; return false; } @@ -193,9 +159,6 @@ uint32_t Verifier::EvaluateBPF(const std::vector<struct sock_filter>& program, return 0; } return r; } - case BPF_ALU: - Alu(&state, insn, err); - break; default: *err = "Unexpected instruction in BPF program"; break; @@ -285,69 +248,4 @@ uint32_t Verifier::Ret(State *, const struct sock_filter& insn, return insn.k; } -void Verifier::Alu(State *state, const struct sock_filter& insn, - const char **err) { - if (BPF_OP(insn.code) == BPF_NEG) { - state->accumulator = -state->accumulator; - return; - } else { - if (BPF_SRC(insn.code) != BPF_K) { - *err = "Unexpected source operand in arithmetic operation"; - return; - } - switch (BPF_OP(insn.code)) { - case BPF_ADD: - state->accumulator += insn.k; - break; - case BPF_SUB: - state->accumulator -= insn.k; - break; - case BPF_MUL: - state->accumulator *= insn.k; - break; - case BPF_DIV: - if (!insn.k) { - *err = "Illegal division by zero"; - break; - } - state->accumulator /= insn.k; - break; - case BPF_MOD: - if (!insn.k) { - *err = "Illegal division by zero"; - break; - } - state->accumulator %= insn.k; - break; - case BPF_OR: - state->accumulator |= insn.k; - break; - case BPF_XOR: - state->accumulator ^= insn.k; - break; - case BPF_AND: - state->accumulator &= insn.k; - break; - case BPF_LSH: - if (insn.k > 32) { - *err = "Illegal shift operation"; - break; - } - state->accumulator <<= insn.k; - break; - case BPF_RSH: - if (insn.k > 32) { - *err = "Illegal shift operation"; - break; - } - state->accumulator >>= insn.k; - break; - default: - *err = "Invalid operator in arithmetic operation"; - break; - } - } -} - - } // namespace diff --git a/sandbox/linux/seccomp-bpf/verifier.h b/sandbox/linux/seccomp-bpf/verifier.h index 26a3156..f66e7e93 100644 --- a/sandbox/linux/seccomp-bpf/verifier.h +++ b/sandbox/linux/seccomp-bpf/verifier.h @@ -69,8 +69,6 @@ class Verifier { const char **err); static uint32_t Ret(State *state, const struct sock_filter& insn, const char **err); - static void Alu(State *state, const struct sock_filter& insn, - const char **err); DISALLOW_IMPLICIT_CONSTRUCTORS(Verifier); }; |