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 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
855 | 858 |
856 Instruction* SandboxBPF::RetExpression(CodeGen* gen, const ErrorCode& err) { | 859 Instruction* SandboxBPF::RetExpression(CodeGen* gen, const ErrorCode& err) { |
857 if (err.error_type_ == ErrorCode::ET_COND) { | 860 if (err.error_type_ == ErrorCode::ET_COND) { |
858 return CondExpression(gen, err); | 861 return CondExpression(gen, err); |
859 } else { | 862 } else { |
860 return gen->MakeInstruction(BPF_RET + BPF_K, err); | 863 return gen->MakeInstruction(BPF_RET + BPF_K, err); |
861 } | 864 } |
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 // Sanity check that |cond| makes sense. |
866 // CPU registers. | |
867 if (cond.argno_ < 0 || cond.argno_ >= 6) { | 869 if (cond.argno_ < 0 || cond.argno_ >= 6) { |
868 SANDBOX_DIE( | 870 SANDBOX_DIE("sandbox_bpf: invalid argument number"); |
869 "Internal compiler error; invalid argument number " | 871 } |
870 "encountered"); | 872 if (cond.width_ != ErrorCode::TP_32BIT && |
873 cond.width_ != ErrorCode::TP_64BIT) { | |
874 SANDBOX_DIE("sandbox_bpf: invalid argument width"); | |
875 } | |
876 if (cond.mask_ == 0) { | |
877 SANDBOX_DIE("sandbox_bpf: zero mask is invalid"); | |
878 } | |
879 if ((cond.value_ & cond.mask_) != cond.value_) { | |
880 SANDBOX_DIE("sandbox_bpf: value contains masked out bits"); | |
881 } | |
882 if (cond.width_ == ErrorCode::TP_32BIT && | |
883 ((cond.mask_ >> 32) != 0 || (cond.value_ >> 32) != 0)) { | |
884 SANDBOX_DIE("sandbox_bpf: test exceeds argument size"); | |
885 } | |
886 if (cond.width_ == ErrorCode::TP_64BIT && sizeof(void*) != 8) { | |
887 SANDBOX_DIE("sandbox_bpf: 64-bit argument on 32-bit machine"); | |
871 } | 888 } |
872 | 889 |
873 // BPF programs operate on 32bit entities. Load both halfs of the 64bit | 890 Instruction* passed = RetExpression(gen, *cond.passed_); |
874 // system call argument and then generate suitable conditional statements. | 891 Instruction* failed = RetExpression(gen, *cond.failed_); |
875 Instruction* msb_head = gen->MakeInstruction( | |
876 BPF_LD + BPF_W + BPF_ABS, SECCOMP_ARG_MSB_IDX(cond.argno_)); | |
877 Instruction* msb_tail = msb_head; | |
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 | 892 |
882 // Emit a suitable comparison statement. | 893 // We want to emit code to check "(arg & mask) == value" where arg, mask, and |
883 switch (cond.op_) { | 894 // value are 64-bit values, but the BPF machine is only 32-bit. We implement |
884 case ErrorCode::OP_EQUAL: | 895 // this by independently testing the upper and lower 32-bits and continuing to |
885 // Compare the least significant bits for equality | 896 // |passed| if both evaluate true, or to |failed| if either evaluate false. |
886 lsb_tail = gen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, | 897 return CondExpressionHalf( |
887 static_cast<uint32_t>(cond.value_), | 898 gen, |
888 RetExpression(gen, *cond.passed_), | 899 cond, |
889 RetExpression(gen, *cond.failed_)); | 900 UpperHalf, |
890 gen->JoinInstructions(lsb_head, lsb_tail); | 901 CondExpressionHalf(gen, cond, LowerHalf, passed, failed), |
902 failed); | |
903 } | |
891 | 904 |
892 // If we are looking at a 64bit argument, we need to also compare the | 905 Instruction* SandboxBPF::CondExpressionHalf(CodeGen* gen, |
893 // most significant bits. | 906 const ErrorCode& cond, |
894 if (cond.width_ == ErrorCode::TP_64BIT) { | 907 ArgHalf half, |
895 msb_tail = | 908 Instruction* passed, |
896 gen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, | 909 Instruction* failed) { |
897 static_cast<uint32_t>(cond.value_ >> 32), | 910 if (cond.width_ == ErrorCode::TP_32BIT && half == UpperHalf) { |
898 lsb_head, | 911 // Special logic for sanity checking the upper 32-bits of 32-bit system |
899 RetExpression(gen, *cond.failed_)); | 912 // call arguments. |
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 | 913 |
941 // If we are looking at a 64bit argument, we need to also check the bits | 914 // TODO(mdempsky): Compile Unexpected64bitArgument() just per program. |
942 // in the MSB half of the system call argument. | 915 Instruction* invalid_64bit = RetExpression(gen, Unexpected64bitArgument()); |
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 | 916 |
992 // If we are looking at a 64bit argument, we need to also check the bits | 917 const uint32_t upper = SECCOMP_ARG_MSB_IDX(cond.argno_); |
993 // in the MSB half of the system call argument. | 918 const uint32_t lower = SECCOMP_ARG_LSB_IDX(cond.argno_); |
994 if (cond.width_ == ErrorCode::TP_64BIT) { | 919 |
995 uint32_t msb_bits = static_cast<uint32_t>(cond.value_ >> 32); | 920 if (sizeof(void*) == 4) { |
996 if (!msb_bits) { | 921 // On 32-bit platforms, the upper 32-bits should always be 0: |
997 // No bits are set in the MSB half. The test will always fail. | 922 // LDW [upper] |
998 msb_head = lsb_head; | 923 // JEQ 0, passed, invalid |
999 } else { | 924 return gen->MakeInstruction( |
1000 msb_tail = gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, | 925 BPF_LD + BPF_W + BPF_ABS, |
1001 msb_bits, | 926 upper, |
1002 RetExpression(gen, *cond.passed_), | 927 gen->MakeInstruction( |
1003 lsb_head); | 928 BPF_JMP + BPF_JEQ + BPF_K, 0, passed, invalid_64bit)); |
1004 gen->JoinInstructions(msb_head, msb_tail); | 929 } |
1005 } | 930 |
1006 } | 931 // On 64-bit platforms, the upper 32-bits may be 0 or ~0; but we only allow |
1007 break; | 932 // ~0 if the sign bit of the lower 32-bits is set too: |
1008 default: | 933 // LDW [upper] |
1009 // TODO(markus): Need to add support for OP_GREATER | 934 // JEQ 0, passed, (next) |
1010 SANDBOX_DIE("Not implemented"); | 935 // JEQ ~0, (next), invalid |
1011 break; | 936 // LDW [lower] |
937 // JSET (1<<31), passed, invalid | |
938 // | |
939 // TODO(mdempsky): The JSET instruction could perhaps jump to passed->next | |
940 // instead, as the first instruction of passed should be "LDW [lower]". | |
941 return gen->MakeInstruction( | |
942 BPF_LD + BPF_W + BPF_ABS, | |
943 upper, | |
944 gen->MakeInstruction( | |
945 BPF_JMP + BPF_JEQ + BPF_K, | |
946 0, | |
947 passed, | |
948 gen->MakeInstruction( | |
949 BPF_JMP + BPF_JEQ + BPF_K, | |
950 std::numeric_limits<uint32_t>::max(), | |
951 gen->MakeInstruction( | |
952 BPF_LD + BPF_W + BPF_ABS, | |
953 lower, | |
954 gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, | |
955 1U << 31, | |
956 passed, | |
957 invalid_64bit)), | |
958 invalid_64bit))); | |
1012 } | 959 } |
1013 | 960 |
1014 // Ensure that we never pass a 64bit value, when we only expect a 32bit | 961 const uint32_t idx = (half == UpperHalf) ? SECCOMP_ARG_MSB_IDX(cond.argno_) |
1015 // value. This is somewhat complicated by the fact that on 64bit systems, | 962 : SECCOMP_ARG_LSB_IDX(cond.argno_); |
1016 // callers could legitimately pass in a non-zero value in the MSB, iff the | 963 const uint32_t mask = (half == UpperHalf) ? cond.mask_ >> 32 : cond.mask_; |
1017 // LSB has been sign-extended into the MSB. | 964 const uint32_t value = (half == UpperHalf) ? cond.value_ >> 32 : cond.value_; |
1018 if (cond.width_ == ErrorCode::TP_32BIT) { | |
1019 if (cond.value_ >> 32) { | |
1020 SANDBOX_DIE( | |
1021 "Invalid comparison of a 32bit system call argument " | |
1022 "against a 64bit constant; this test is always false."); | |
1023 } | |
1024 | 965 |
1025 Instruction* invalid_64bit = RetExpression(gen, Unexpected64bitArgument()); | 966 // Emit a suitable instruction sequence for (arg & mask) == value. |
1026 #if __SIZEOF_POINTER__ > 4 | 967 |
1027 invalid_64bit = gen->MakeInstruction( | 968 // For (arg & 0) == 0, just return passed. |
1028 BPF_JMP + BPF_JEQ + BPF_K, | 969 if (mask == 0) { |
1029 0xFFFFFFFF, | 970 CHECK_EQ(0U, value); |
1030 gen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, | 971 return passed; |
1031 SECCOMP_ARG_LSB_IDX(cond.argno_), | |
1032 gen->MakeInstruction(BPF_JMP + BPF_JGE + BPF_K, | |
1033 0x80000000, | |
1034 lsb_head, | |
1035 invalid_64bit)), | |
1036 invalid_64bit); | |
1037 #endif | |
1038 gen->JoinInstructions( | |
1039 msb_tail, | |
1040 gen->MakeInstruction( | |
1041 BPF_JMP + BPF_JEQ + BPF_K, 0, lsb_head, invalid_64bit)); | |
1042 } | 972 } |
1043 | 973 |
1044 return msb_head; | 974 // For (arg & ~0) == value, emit: |
975 // LDW [idx] | |
976 // JEQ value, passed, failed | |
977 if (mask == std::numeric_limits<uint32_t>::max()) { | |
978 return gen->MakeInstruction( | |
979 BPF_LD + BPF_W + BPF_ABS, | |
980 idx, | |
981 gen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed)); | |
982 } | |
983 | |
984 // For (arg & mask) == 0, emit: | |
985 // LDW [idx] | |
986 // JSET mask, failed, passed | |
987 // (Note: failed and passed are intentionally swapped.) | |
988 if (value == 0) { | |
989 return gen->MakeInstruction( | |
990 BPF_LD + BPF_W + BPF_ABS, | |
991 idx, | |
992 gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, mask, failed, passed)); | |
993 } | |
994 | |
995 // For (arg & x) == x where x is a single-bit value, emit: | |
996 // LDW [idx] | |
997 // JSET mask, passed, failed | |
998 if (mask == value && HasExactlyOneBit(mask)) { | |
999 return gen->MakeInstruction( | |
1000 BPF_LD + BPF_W + BPF_ABS, | |
1001 idx, | |
1002 gen->MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, mask, passed, failed)); | |
1003 } | |
1004 | |
1005 // Generic fallback: | |
1006 // LDW [idx] | |
1007 // AND mask | |
1008 // JEQ value, passed, failed | |
1009 return gen->MakeInstruction( | |
1010 BPF_LD + BPF_W + BPF_ABS, | |
1011 idx, | |
1012 gen->MakeInstruction( | |
1013 BPF_ALU + BPF_AND + BPF_K, | |
1014 mask, | |
1015 gen->MakeInstruction( | |
1016 BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed))); | |
1045 } | 1017 } |
1046 | 1018 |
1047 ErrorCode SandboxBPF::Unexpected64bitArgument() { | 1019 ErrorCode SandboxBPF::Unexpected64bitArgument() { |
1048 return Kill("Unexpected 64bit argument detected"); | 1020 return Kill("Unexpected 64bit argument detected"); |
1049 } | 1021 } |
1050 | 1022 |
1051 ErrorCode SandboxBPF::Trap(Trap::TrapFnc fnc, const void* aux) { | 1023 ErrorCode SandboxBPF::Trap(Trap::TrapFnc fnc, const void* aux) { |
1052 return Trap::MakeTrap(fnc, aux, true /* Safe Trap */); | 1024 return Trap::MakeTrap(fnc, aux, true /* Safe Trap */); |
1053 } | 1025 } |
1054 | 1026 |
(...skipping 17 matching lines...) Expand all Loading... | |
1072 intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) { | 1044 intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) { |
1073 return Syscall::Call(args.nr, | 1045 return Syscall::Call(args.nr, |
1074 static_cast<intptr_t>(args.args[0]), | 1046 static_cast<intptr_t>(args.args[0]), |
1075 static_cast<intptr_t>(args.args[1]), | 1047 static_cast<intptr_t>(args.args[1]), |
1076 static_cast<intptr_t>(args.args[2]), | 1048 static_cast<intptr_t>(args.args[2]), |
1077 static_cast<intptr_t>(args.args[3]), | 1049 static_cast<intptr_t>(args.args[3]), |
1078 static_cast<intptr_t>(args.args[4]), | 1050 static_cast<intptr_t>(args.args[4]), |
1079 static_cast<intptr_t>(args.args[5])); | 1051 static_cast<intptr_t>(args.args[5])); |
1080 } | 1052 } |
1081 | 1053 |
1054 ErrorCode SandboxBPF::CondMaskedEqual(int argno, | |
1055 ErrorCode::ArgType width, | |
1056 uint64_t mask, | |
1057 uint64_t value, | |
1058 const ErrorCode& passed, | |
1059 const ErrorCode& failed) { | |
1060 return ErrorCode(argno, | |
1061 width, | |
1062 mask, | |
1063 value, | |
1064 &*conds_->insert(passed).first, | |
1065 &*conds_->insert(failed).first); | |
1066 } | |
1067 | |
1082 ErrorCode SandboxBPF::Cond(int argno, | 1068 ErrorCode SandboxBPF::Cond(int argno, |
1083 ErrorCode::ArgType width, | 1069 ErrorCode::ArgType width, |
1084 ErrorCode::Operation op, | 1070 ErrorCode::Operation op, |
1085 uint64_t value, | 1071 uint64_t value, |
1086 const ErrorCode& passed, | 1072 const ErrorCode& passed, |
1087 const ErrorCode& failed) { | 1073 const ErrorCode& failed) { |
1088 return ErrorCode(argno, | 1074 // CondExpression() currently rejects mask==0 as invalid, but there are |
1089 width, | 1075 // SandboxBPF unit tests that (questionably) expect OP_HAS_{ANY,ALL}_BITS to |
1090 op, | 1076 // work with value==0. To keep those tests working for now, we specially |
1091 value, | 1077 // convert value==0 here. |
jln (very slow on Chromium)
2014/09/04 21:45:05
Should this comment be below (inside the switch) ?
| |
1092 &*conds_->insert(passed).first, | 1078 |
1093 &*conds_->insert(failed).first); | 1079 switch (op) { |
1080 case ErrorCode::OP_EQUAL: { | |
1081 // Convert to "(arg & ~0) == value". | |
1082 const uint64_t mask = (width == ErrorCode::TP_64BIT) | |
1083 ? std::numeric_limits<uint64_t>::max() | |
1084 : std::numeric_limits<uint32_t>::max(); | |
1085 return CondMaskedEqual(argno, width, mask, value, passed, failed); | |
1086 } | |
1087 | |
1088 case ErrorCode::OP_HAS_ALL_BITS: | |
1089 if (value == 0) { | |
1090 // Always passes. | |
1091 return passed; | |
1092 } | |
1093 // Convert to "(arg & value) == value". | |
1094 return CondMaskedEqual(argno, width, value, value, passed, failed); | |
1095 | |
1096 case ErrorCode::OP_HAS_ANY_BITS: | |
1097 if (value == 0) { | |
1098 // Always fails. | |
1099 return failed; | |
1100 } | |
1101 // Convert to "(arg & value) == 0", but swap passed and failed. | |
1102 return CondMaskedEqual(argno, width, value, 0, failed, passed); | |
1103 | |
1104 default: | |
1105 SANDBOX_DIE("Not implemented"); | |
1106 } | |
1094 } | 1107 } |
1095 | 1108 |
1096 ErrorCode SandboxBPF::Kill(const char* msg) { | 1109 ErrorCode SandboxBPF::Kill(const char* msg) { |
1097 return Trap(BPFFailure, const_cast<char*>(msg)); | 1110 return Trap(BPFFailure, const_cast<char*>(msg)); |
1098 } | 1111 } |
1099 | 1112 |
1100 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; | 1113 SandboxBPF::SandboxStatus SandboxBPF::status_ = STATUS_UNKNOWN; |
1101 | 1114 |
1102 } // namespace sandbox | 1115 } // namespace sandbox |
OLD | NEW |