Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 5 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
| 6 | 6 |
| 7 // Some headers on Android are missing cdefs: crbug.com/172337. | 7 // Some headers on Android are missing cdefs: crbug.com/172337. |
| 8 // (We can't use OS_ANDROID here since build_config.h is not included). | 8 // (We can't use OS_ANDROID here since build_config.h is not included). |
| 9 #if defined(ANDROID) | 9 #if defined(ANDROID) |
| 10 #include <sys/cdefs.h> | 10 #include <sys/cdefs.h> |
| 11 #endif | 11 #endif |
| 12 | 12 |
| 13 #include <errno.h> | 13 #include <errno.h> |
| 14 #include <fcntl.h> | 14 #include <fcntl.h> |
| 15 #include <string.h> | 15 #include <string.h> |
| 16 #include <sys/prctl.h> | 16 #include <sys/prctl.h> |
| 17 #include <sys/stat.h> | 17 #include <sys/stat.h> |
| 18 #include <sys/syscall.h> | 18 #include <sys/syscall.h> |
| 19 #include <sys/types.h> | 19 #include <sys/types.h> |
| 20 #include <time.h> | 20 #include <time.h> |
| 21 #include <unistd.h> | 21 #include <unistd.h> |
| 22 | 22 |
| 23 #include <limits> | |
| 24 | |
| 23 #include "base/compiler_specific.h" | 25 #include "base/compiler_specific.h" |
| 24 #include "base/logging.h" | 26 #include "base/logging.h" |
| 25 #include "base/macros.h" | 27 #include "base/macros.h" |
| 26 #include "base/memory/scoped_ptr.h" | 28 #include "base/memory/scoped_ptr.h" |
| 27 #include "base/posix/eintr_wrapper.h" | 29 #include "base/posix/eintr_wrapper.h" |
| 28 #include "sandbox/linux/seccomp-bpf/codegen.h" | 30 #include "sandbox/linux/seccomp-bpf/codegen.h" |
| 29 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" | 31 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" |
| 30 #include "sandbox/linux/seccomp-bpf/syscall.h" | 32 #include "sandbox/linux/seccomp-bpf/syscall.h" |
| 31 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" | 33 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" |
| 32 #include "sandbox/linux/seccomp-bpf/verifier.h" | 34 #include "sandbox/linux/seccomp-bpf/verifier.h" |
| 33 #include "sandbox/linux/services/linux_syscalls.h" | 35 #include "sandbox/linux/services/linux_syscalls.h" |
| 34 | 36 |
| 35 namespace sandbox { | 37 namespace sandbox { |
| 36 | 38 |
| 37 namespace { | 39 namespace { |
| 38 | 40 |
| 39 const int kExpectedExitCode = 100; | 41 const int kExpectedExitCode = 100; |
| 40 | 42 |
| 41 int popcount(uint32_t x) { | 43 bool HasExactlyOneBit(uint64_t x) { |
| 42 return __builtin_popcount(x); | 44 // Common trick; e.g., see http://stackoverflow.com/a/108329. |
| 45 return x != 0 && (x & (x - 1)) == 0; | |
| 43 } | 46 } |
| 44 | 47 |
| 45 #if !defined(NDEBUG) | 48 #if !defined(NDEBUG) |
| 46 void WriteFailedStderrSetupMessage(int out_fd) { | 49 void WriteFailedStderrSetupMessage(int out_fd) { |
| 47 const char* error_string = strerror(errno); | 50 const char* error_string = strerror(errno); |
| 48 static const char msg[] = | 51 static const char msg[] = |
| 49 "You have reproduced a puzzling issue.\n" | 52 "You have reproduced a puzzling issue.\n" |
| 50 "Please, report to crbug.com/152530!\n" | 53 "Please, report to crbug.com/152530!\n" |
| 51 "Failed to set up stderr: "; | 54 "Failed to set up stderr: "; |
| 52 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string && | 55 if (HANDLE_EINTR(write(out_fd, msg, sizeof(msg) - 1)) > 0 && error_string && |
| (...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 862 } | 865 } |
| 863 | 866 |
| 864 Instruction* SandboxBPF::CondExpression(CodeGen* gen, const ErrorCode& cond) { | 867 Instruction* SandboxBPF::CondExpression(CodeGen* gen, const ErrorCode& cond) { |
| 865 // We can only inspect the six system call arguments that are passed in | 868 // We can only inspect the six system call arguments that are passed in |
| 866 // CPU registers. | 869 // CPU registers. |
| 867 if (cond.argno_ < 0 || cond.argno_ >= 6) { | 870 if (cond.argno_ < 0 || cond.argno_ >= 6) { |
| 868 SANDBOX_DIE( | 871 SANDBOX_DIE( |
| 869 "Internal compiler error; invalid argument number " | 872 "Internal compiler error; invalid argument number " |
| 870 "encountered"); | 873 "encountered"); |
| 871 } | 874 } |
| 872 | 875 if (cond.width_ != ErrorCode::TP_32BIT && |
| 873 // BPF programs operate on 32bit entities. Load both halfs of the 64bit | 876 cond.width_ != ErrorCode::TP_64BIT) { |
| 874 // system call argument and then generate suitable conditional statements. | 877 SANDBOX_DIE("Internal compiler error; invalid argument width"); |
| 875 Instruction* msb_head = gen->MakeInstruction( | 878 } |
| 876 BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARG_MSB_IDX(cond.argno_)); | 879 if ((cond.value_ & cond.mask_) != cond.value_) { |
| 877 Instruction* msb_tail = msb_head; | 880 SANDBOX_DIE("Internal compiler error; invalid masked value"); |
| 878 Instruction* lsb_head = gen->MakeInstruction( | |
| 879 BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARG_LSB_IDX(cond.argno_)); | |
| 880 Instruction* lsb_tail = lsb_head; | |
| 881 | |
| 882 // Emit a suitable comparison statement. | |
| 883 switch (cond.op_) { | |
| 884 case ErrorCode::OP_EQUAL: | |
| 885 // Compare the least significant bits for equality | |
| 886 lsb_tail = gen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, | |
| 887 static_cast<uint32_t>(cond.value_), | |
| 888 RetExpression(gen, *cond.passed_), | |
| 889 RetExpression(gen, *cond.failed_)); | |
| 890 gen->JoinInstructions(lsb_head, lsb_tail); | |
| 891 | |
| 892 // If we are looking at a 64bit argument, we need to also compare the | |
| 893 // most significant bits. | |
| 894 if (cond.width_ == ErrorCode::TP_64BIT) { | |
| 895 msb_tail = | |
| 896 gen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, | |
| 897 static_cast<uint32_t>(cond.value_ >> 32), | |
| 898 lsb_head, | |
| 899 RetExpression(gen, *cond.failed_)); | |
| 900 gen->JoinInstructions(msb_head, msb_tail); | |
| 901 } | |
| 902 break; | |
| 903 case ErrorCode::OP_HAS_ALL_BITS: | |
| 904 // Check the bits in the LSB half of the system call argument. Our | |
| 905 // OP_HAS_ALL_BITS operator passes, iff all of the bits are set. This is | |
| 906 // different from the kernel's BPF_JSET operation which passes, if any of | |
| 907 // the bits are set. | |
| 908 // Of course, if there is only a single set bit (or none at all), then | |
| 909 // things get easier. | |
| 910 { | |
| 911 uint32_t lsb_bits = static_cast<uint32_t>(cond.value_); | |
| 912 int lsb_bit_count = popcount(lsb_bits); | |
| 913 if (lsb_bit_count == 0) { | |
| 914 // No bits are set in the LSB half. The test will always pass. | |
| 915 lsb_head = RetExpression(gen, *cond.passed_); | |
| 916 lsb_tail = NULL; | |
| 917 } else if (lsb_bit_count == 1) { | |
| 918 // Exactly one bit is set in the LSB half. We can use the BPF_JSET | |
| 919 // operator. | |
| 920 lsb_tail = gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, | |
| 921 lsb_bits, | |
| 922 RetExpression(gen, *cond.passed_), | |
| 923 RetExpression(gen, *cond.failed_)); | |
| 924 gen->JoinInstructions(lsb_head, lsb_tail); | |
| 925 } else { | |
| 926 // More than one bit is set in the LSB half. We need to combine | |
| 927 // BPF_AND and BPF_JEQ to test whether all of these bits are in fact | |
| 928 // set in the system call argument. | |
| 929 gen->JoinInstructions( | |
| 930 lsb_head, | |
| 931 gen->MakeInstruction(BPF_ALU + BPF_AND + BPF_K, | |
| 932 lsb_bits, | |
| 933 lsb_tail = gen->MakeInstruction( | |
| 934 BPF_JMP + BPF_JEQ + BPF_K, | |
| 935 lsb_bits, | |
| 936 RetExpression(gen, *cond.passed_), | |
| 937 RetExpression(gen, *cond.failed_)))); | |
| 938 } | |
| 939 } | |
| 940 | |
| 941 // If we are looking at a 64bit argument, we need to also check the bits | |
| 942 // in the MSB half of the system call argument. | |
| 943 if (cond.width_ == ErrorCode::TP_64BIT) { | |
| 944 uint32_t msb_bits = static_cast<uint32_t>(cond.value_ >> 32); | |
| 945 int msb_bit_count = popcount(msb_bits); | |
| 946 if (msb_bit_count == 0) { | |
| 947 // No bits are set in the MSB half. The test will always pass. | |
| 948 msb_head = lsb_head; | |
| 949 } else if (msb_bit_count == 1) { | |
| 950 // Exactly one bit is set in the MSB half. We can use the BPF_JSET | |
| 951 // operator. | |
| 952 msb_tail = gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, | |
| 953 msb_bits, | |
| 954 lsb_head, | |
| 955 RetExpression(gen, *cond.failed_)); | |
| 956 gen->JoinInstructions(msb_head, msb_tail); | |
| 957 } else { | |
| 958 // More than one bit is set in the MSB half. We need to combine | |
| 959 // BPF_AND and BPF_JEQ to test whether all of these bits are in fact | |
| 960 // set in the system call argument. | |
| 961 gen->JoinInstructions( | |
| 962 msb_head, | |
| 963 gen->MakeInstruction( | |
| 964 BPF_ALU + BPF_AND + BPF_K, | |
| 965 msb_bits, | |
| 966 gen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, | |
| 967 msb_bits, | |
| 968 lsb_head, | |
| 969 RetExpression(gen, *cond.failed_)))); | |
| 970 } | |
| 971 } | |
| 972 break; | |
| 973 case ErrorCode::OP_HAS_ANY_BITS: | |
| 974 // Check the bits in the LSB half of the system call argument. Our | |
| 975 // OP_HAS_ANY_BITS operator passes, iff any of the bits are set. This maps | |
| 976 // nicely to the kernel's BPF_JSET operation. | |
| 977 { | |
| 978 uint32_t lsb_bits = static_cast<uint32_t>(cond.value_); | |
| 979 if (!lsb_bits) { | |
| 980 // No bits are set in the LSB half. The test will always fail. | |
| 981 lsb_head = RetExpression(gen, *cond.failed_); | |
| 982 lsb_tail = NULL; | |
| 983 } else { | |
| 984 lsb_tail = gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, | |
| 985 lsb_bits, | |
| 986 RetExpression(gen, *cond.passed_), | |
| 987 RetExpression(gen, *cond.failed_)); | |
| 988 gen->JoinInstructions(lsb_head, lsb_tail); | |
| 989 } | |
| 990 } | |
| 991 | |
| 992 // If we are looking at a 64bit argument, we need to also check the bits | |
| 993 // in the MSB half of the system call argument. | |
| 994 if (cond.width_ == ErrorCode::TP_64BIT) { | |
| 995 uint32_t msb_bits = static_cast<uint32_t>(cond.value_ >> 32); | |
| 996 if (!msb_bits) { | |
| 997 // No bits are set in the MSB half. The test will always fail. | |
| 998 msb_head = lsb_head; | |
| 999 } else { | |
| 1000 msb_tail = gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, | |
| 1001 msb_bits, | |
| 1002 RetExpression(gen, *cond.passed_), | |
| 1003 lsb_head); | |
| 1004 gen->JoinInstructions(msb_head, msb_tail); | |
| 1005 } | |
| 1006 } | |
| 1007 break; | |
| 1008 default: | |
| 1009 // TODO(markus): Need to add support for OP_GREATER | |
| 1010 SANDBOX_DIE("Not implemented"); | |
| 1011 break; | |
| 1012 } | 881 } |
| 1013 | 882 |
| 1014 // Ensure that we never pass a 64bit value, when we only expect a 32bit | 883 Instruction* passed = RetExpression(gen, *cond.passed_); |
| 1015 // value. This is somewhat complicated by the fact that on 64bit systems, | 884 Instruction* failed = RetExpression(gen, *cond.failed_); |
| 1016 // callers could legitimately pass in a non-zero value in the MSB, iff the | 885 |
| 1017 // LSB has been sign-extended into the MSB. | 886 // We want to emit code to check "(arg & mask) == value" where arg, mask, and |
| 1018 if (cond.width_ == ErrorCode::TP_32BIT) { | 887 // value are 64-bit values, but the BPF machine is only 32-bit. We implement |
| 1019 if (cond.value_ >> 32) { | 888 // this by independently testing the upper and lower 32-bits and continuing to |
| 889 // "passed" if both evaluate true, or to "failed" if either evaluate false. | |
| 890 return CondExpressionHalf( | |
| 891 gen, | |
| 892 cond, | |
| 893 UpperHalf, | |
| 894 CondExpressionHalf(gen, cond, LowerHalf, passed, failed), | |
| 895 failed); | |
| 896 } | |
| 897 | |
| 898 Instruction* SandboxBPF::CondExpressionHalf(CodeGen* gen, | |
| 899 const ErrorCode& cond, | |
| 900 ArgHalf half, | |
| 901 Instruction* passed, | |
| 902 Instruction* failed) { | |
| 903 if (cond.width_ == ErrorCode::TP_32BIT && half == UpperHalf) { | |
| 904 // Special logic for sanity checking the upper 32-bits of 32-bit system | |
| 905 // call arguments. | |
| 906 | |
| 907 if ((cond.mask_ >> 32) != 0) { | |
| 1020 SANDBOX_DIE( | 908 SANDBOX_DIE( |
| 1021 "Invalid comparison of a 32bit system call argument " | 909 "Invalid comparison of a 32bit system call argument " |
| 1022 "against a 64bit constant; this test is always false."); | 910 "against a 64bit constant; this test is always false."); |
| 1023 } | 911 } |
| 1024 | 912 |
| 913 // TODO(mdempsky): Compile Unexpected64bitArgument() just per program. | |
| 1025 Instruction* invalid_64bit = RetExpression(gen, Unexpected64bitArgument()); | 914 Instruction* invalid_64bit = RetExpression(gen, Unexpected64bitArgument()); |
| 1026 #if __SIZEOF_POINTER__ > 4 | 915 |
| 1027 invalid_64bit = gen->MakeInstruction( | 916 const uint32_t upper = SECCOMP_ARG_MSB_IDX(cond.argno_); |
| 1028 BPF_JMP + BPF_JEQ + BPF_K, | 917 const uint32_t lower = SECCOMP_ARG_LSB_IDX(cond.argno_); |
| 1029 0xFFFFFFFF, | 918 |
| 1030 gen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, | 919 if (sizeof(void*) == 4) { |
| 1031 SECCOMP_ARG_LSB_IDX(cond.argno_), | 920 // On 32-bit platforms, the upper 32-bits should always be 0: |
|
jln (very slow on Chromium)
2014/09/04 02:08:36
I think it would be redundant with your previous c
mdempsky
2014/09/04 17:26:48
Yeah, it should be redundant, but I went ahead and
| |
| 1032 gen->MakeInstruction(BPF_JMP + BPF_JGE + BPF_K, | 921 // LDW [upper] |
| 1033 0x80000000, | 922 // JEQ 0, passed, invalid |
| 1034 lsb_head, | 923 return gen->MakeInstruction( |
| 1035 invalid_64bit)), | 924 BPF_LD + BPF_W + BPF_ABS, |
| 1036 invalid_64bit); | 925 upper, |
| 1037 #endif | 926 gen->MakeInstruction( |
| 1038 gen->JoinInstructions( | 927 BPF_JMP + BPF_JEQ + BPF_K, 0, passed, invalid_64bit)); |
| 1039 msb_tail, | 928 } |
| 929 | |
| 930 // On 64-bit platforms, the upper 32-bits may be 0 or ~0; but we only allow | |
| 931 // ~0 if the sign bit of the lower 32-bits is set too: | |
| 932 // LDW [upper] | |
| 933 // JEQ 0, passed, (next) | |
| 934 // JEQ ~0, (next), invalid | |
| 935 // LDW [lower] | |
| 936 // JSET (1<<31), passed, invalid | |
| 937 // | |
| 938 // TODO(mdempsky): The JSET instruction could perhaps jump to passed->next | |
| 939 // instead, as the first instruction of passed should be "LDW [lower]". | |
| 940 return gen->MakeInstruction( | |
| 941 BPF_LD + BPF_W + BPF_ABS, | |
| 942 upper, | |
| 1040 gen->MakeInstruction( | 943 gen->MakeInstruction( |
| 1041 BPF_JMP + BPF_JEQ + BPF_K, 0, lsb_head, invalid_64bit)); | 944 BPF_JMP + BPF_JEQ + BPF_K, |
| 945 0, | |
| 946 passed, | |
| 947 gen->MakeInstruction( | |
| 948 BPF_JMP + BPF_JEQ + BPF_K, | |
| 949 std::numeric_limits<uint32_t>::max(), | |
| 950 gen->MakeInstruction( | |
| 951 BPF_LD + BPF_W + BPF_ABS, | |
| 952 lower, | |
| 953 gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, | |
| 954 1U << 31, | |
| 955 passed, | |
| 956 invalid_64bit)), | |
| 957 invalid_64bit))); | |
| 1042 } | 958 } |
| 1043 | 959 |
| 1044 return msb_head; | 960 const uint32_t idx = (half == UpperHalf) ? SECCOMP_ARG_MSB_IDX(cond.argno_) |
| 961 : SECCOMP_ARG_LSB_IDX(cond.argno_); | |
| 962 const uint32_t mask = (half == UpperHalf) ? cond.mask_ >> 32 : cond.mask_; | |
| 963 const uint32_t value = (half == UpperHalf) ? cond.value_ >> 32 : cond.value_; | |
| 964 | |
| 965 // Emit a suitable instruction sequence for (arg & mask) == value. | |
| 966 | |
| 967 // For (arg & 0) == 0, just return passed. | |
| 968 if (mask == 0) { | |
| 969 return passed; | |
|
jln (very slow on Chromium)
2014/09/04 02:08:35
Shouldn't you assert that value == 0 here again? T
mdempsky
2014/09/04 17:26:48
Fair enough, done.
| |
| 970 } | |
| 971 | |
| 972 // For (arg & ~0) == value, emit: | |
| 973 // LDW [idx] | |
| 974 // JEQ value, passed, failed | |
| 975 if (mask == std::numeric_limits<uint32_t>::max()) { | |
| 976 return gen->MakeInstruction( | |
| 977 BPF_LD + BPF_W + BPF_ABS, | |
| 978 idx, | |
| 979 gen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed)); | |
| 980 } | |
| 981 | |
| 982 // For (arg & mask) == 0, emit: | |
| 983 // LDW [idx] | |
| 984 // JSET mask, failed, passed | |
| 985 // (Note: failed and passed are intentionally swapped.) | |
| 986 if (value == 0) { | |
| 987 return gen->MakeInstruction( | |
| 988 BPF_LD + BPF_W + BPF_ABS, | |
| 989 idx, | |
| 990 gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, mask, failed, passed)); | |
| 991 } | |
| 992 | |
| 993 // For (arg & x) == x where x is a single-bit value, emit: | |
| 994 // LDW [idx] | |
| 995 // JSET mask, passed, failed | |
| 996 if (mask == value && HasExactlyOneBit(mask)) { | |
| 997 return gen->MakeInstruction( | |
| 998 BPF_LD + BPF_W + BPF_ABS, | |
| 999 idx, | |
| 1000 gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, mask, passed, failed)); | |
| 1001 } | |
| 1002 | |
| 1003 // Generic fallback: | |
| 1004 // LDW [idx] | |
| 1005 // AND mask | |
| 1006 // JEQ value, passed, failed | |
| 1007 return gen->MakeInstruction( | |
| 1008 BPF_LD + BPF_W + BPF_ABS, | |
| 1009 idx, | |
| 1010 gen->MakeInstruction( | |
| 1011 BPF_ALU + BPF_AND + BPF_K, | |
| 1012 mask, | |
| 1013 gen->MakeInstruction( | |
| 1014 BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed))); | |
| 1045 } | 1015 } |
| 1046 | 1016 |
| 1047 ErrorCode SandboxBPF::Unexpected64bitArgument() { | 1017 ErrorCode SandboxBPF::Unexpected64bitArgument() { |
| 1048 return Kill("Unexpected 64bit argument detected"); | 1018 return Kill("Unexpected 64bit argument detected"); |
| 1049 } | 1019 } |
| 1050 | 1020 |
| 1051 ErrorCode SandboxBPF::Trap(Trap::TrapFnc fnc, const void* aux) { | 1021 ErrorCode SandboxBPF::Trap(Trap::TrapFnc fnc, const void* aux) { |
| 1052 return Trap::MakeTrap(fnc, aux, true /* Safe Trap */); | 1022 return Trap::MakeTrap(fnc, aux, true /* Safe Trap */); |
| 1053 } | 1023 } |
| 1054 | 1024 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1072 intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) { | 1042 intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) { |
| 1073 return Syscall::Call(args.nr, | 1043 return Syscall::Call(args.nr, |
| 1074 static_cast<intptr_t>(args.args[0]), | 1044 static_cast<intptr_t>(args.args[0]), |
| 1075 static_cast<intptr_t>(args.args[1]), | 1045 static_cast<intptr_t>(args.args[1]), |
| 1076 static_cast<intptr_t>(args.args[2]), | 1046 static_cast<intptr_t>(args.args[2]), |
| 1077 static_cast<intptr_t>(args.args[3]), | 1047 static_cast<intptr_t>(args.args[3]), |
| 1078 static_cast<intptr_t>(args.args[4]), | 1048 static_cast<intptr_t>(args.args[4]), |
| 1079 static_cast<intptr_t>(args.args[5])); | 1049 static_cast<intptr_t>(args.args[5])); |
| 1080 } | 1050 } |
| 1081 | 1051 |
| 1052 ErrorCode SandboxBPF::CondMaskedEqual(int argno, | |
| 1053 ErrorCode::ArgType width, | |
| 1054 uint64_t mask, | |
| 1055 uint64_t value, | |
| 1056 const ErrorCode& passed, | |
| 1057 const ErrorCode& failed) { | |
| 1058 return ErrorCode(argno, | |
| 1059 width, | |
| 1060 mask, | |
| 1061 value, | |
| 1062 &*conds_->insert(passed).first, | |
| 1063 &*conds_->insert(failed).first); | |
| 1064 } | |
| 1065 | |
| 1082 ErrorCode SandboxBPF::Cond(int argno, | 1066 ErrorCode SandboxBPF::Cond(int argno, |
| 1083 ErrorCode::ArgType width, | 1067 ErrorCode::ArgType width, |
| 1084 ErrorCode::Operation op, | 1068 ErrorCode::Operation op, |
| 1085 uint64_t value, | 1069 uint64_t value, |
| 1086 const ErrorCode& passed, | 1070 const ErrorCode& passed, |
| 1087 const ErrorCode& failed) { | 1071 const ErrorCode& failed) { |
| 1088 return ErrorCode(argno, | 1072 switch (op) { |
| 1089 width, | 1073 case ErrorCode::OP_EQUAL: { |
| 1090 op, | 1074 // Convert to "(arg & ~0) == value". |
| 1091 value, | 1075 const uint64_t mask = (width == ErrorCode::TP_64BIT) |
| 1092 &*conds_->insert(passed).first, | 1076 ? std::numeric_limits<uint64_t>::max() |
| 1093 &*conds_->insert(failed).first); | 1077 : std::numeric_limits<uint32_t>::max(); |
| 1078 return CondMaskedEqual(argno, width, mask, value, passed, failed); | |
| 1079 } | |
| 1080 case ErrorCode::OP_HAS_ALL_BITS: | |
| 1081 // Convert to "(arg & value) == value". | |
| 1082 return CondMaskedEqual(argno, width, value, value, passed, failed); | |
| 1083 case ErrorCode::OP_HAS_ANY_BITS: | |
| 1084 // Convert to "(arg & value) == 0", but swap passed and failed. | |
| 1085 return CondMaskedEqual(argno, width, value, 0, failed, passed); | |
| 1086 default: | |
| 1087 SANDBOX_DIE("Not implemented"); | |
| 1088 } | |
| 1094 } | 1089 } |
| 1095 | 1090 |
| 1096 ErrorCode SandboxBPF::Kill(const char* msg) { | 1091 ErrorCode SandboxBPF::Kill(const char* msg) { |
| 1097 return Trap(BPFFailure, const_cast<char*>(msg)); | 1092 return Trap(BPFFailure, const_cast<char*>(msg)); |
| 1098 } | 1093 } |
| 1099 | 1094 |
| 1100 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; | 1095 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; |
| 1101 | 1096 |
| 1102 } // namespace sandbox | 1097 } // namespace sandbox |
| OLD | NEW |