diff options
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/bpf/jit.c | 27 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 25 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/.gitignore | 1 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 305 |
4 files changed, 308 insertions, 50 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index 662cbc21d909..e23ca90289f7 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c | |||
@@ -3052,26 +3052,19 @@ static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) | |||
3052 | { | 3052 | { |
3053 | const struct bpf_insn *insn = &meta->insn; | 3053 | const struct bpf_insn *insn = &meta->insn; |
3054 | u64 imm = insn->imm; /* sign extend */ | 3054 | u64 imm = insn->imm; /* sign extend */ |
3055 | u8 dst_gpr = insn->dst_reg * 2; | ||
3055 | swreg tmp_reg; | 3056 | swreg tmp_reg; |
3056 | 3057 | ||
3057 | if (!imm) { | 3058 | tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); |
3058 | meta->skip = true; | 3059 | emit_alu(nfp_prog, imm_b(nfp_prog), |
3059 | return 0; | 3060 | reg_a(dst_gpr), ALU_OP_AND, tmp_reg); |
3060 | } | 3061 | /* Upper word of the mask can only be 0 or ~0 from sign extension, |
3061 | 3062 | * so either ignore it or OR the whole thing in. | |
3062 | if (imm & ~0U) { | 3063 | */ |
3063 | tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); | 3064 | if (imm >> 32) |
3064 | emit_alu(nfp_prog, reg_none(), | ||
3065 | reg_a(insn->dst_reg * 2), ALU_OP_AND, tmp_reg); | ||
3066 | emit_br(nfp_prog, BR_BNE, insn->off, 0); | ||
3067 | } | ||
3068 | |||
3069 | if (imm >> 32) { | ||
3070 | tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); | ||
3071 | emit_alu(nfp_prog, reg_none(), | 3065 | emit_alu(nfp_prog, reg_none(), |
3072 | reg_a(insn->dst_reg * 2 + 1), ALU_OP_AND, tmp_reg); | 3066 | reg_a(dst_gpr + 1), ALU_OP_OR, imm_b(nfp_prog)); |
3073 | emit_br(nfp_prog, BR_BNE, insn->off, 0); | 3067 | emit_br(nfp_prog, BR_BNE, insn->off, 0); |
3074 | } | ||
3075 | 3068 | ||
3076 | return 0; | 3069 | return 0; |
3077 | } | 3070 | } |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 5c64281d566e..d27d5a880015 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -3859,6 +3859,12 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode) | |||
3859 | if (tnum_is_const(reg->var_off)) | 3859 | if (tnum_is_const(reg->var_off)) |
3860 | return !tnum_equals_const(reg->var_off, val); | 3860 | return !tnum_equals_const(reg->var_off, val); |
3861 | break; | 3861 | break; |
3862 | case BPF_JSET: | ||
3863 | if ((~reg->var_off.mask & reg->var_off.value) & val) | ||
3864 | return 1; | ||
3865 | if (!((reg->var_off.mask | reg->var_off.value) & val)) | ||
3866 | return 0; | ||
3867 | break; | ||
3862 | case BPF_JGT: | 3868 | case BPF_JGT: |
3863 | if (reg->umin_value > val) | 3869 | if (reg->umin_value > val) |
3864 | return 1; | 3870 | return 1; |
@@ -3943,6 +3949,13 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg, | |||
3943 | */ | 3949 | */ |
3944 | __mark_reg_known(false_reg, val); | 3950 | __mark_reg_known(false_reg, val); |
3945 | break; | 3951 | break; |
3952 | case BPF_JSET: | ||
3953 | false_reg->var_off = tnum_and(false_reg->var_off, | ||
3954 | tnum_const(~val)); | ||
3955 | if (is_power_of_2(val)) | ||
3956 | true_reg->var_off = tnum_or(true_reg->var_off, | ||
3957 | tnum_const(val)); | ||
3958 | break; | ||
3946 | case BPF_JGT: | 3959 | case BPF_JGT: |
3947 | false_reg->umax_value = min(false_reg->umax_value, val); | 3960 | false_reg->umax_value = min(false_reg->umax_value, val); |
3948 | true_reg->umin_value = max(true_reg->umin_value, val + 1); | 3961 | true_reg->umin_value = max(true_reg->umin_value, val + 1); |
@@ -4015,6 +4028,13 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg, | |||
4015 | */ | 4028 | */ |
4016 | __mark_reg_known(false_reg, val); | 4029 | __mark_reg_known(false_reg, val); |
4017 | break; | 4030 | break; |
4031 | case BPF_JSET: | ||
4032 | false_reg->var_off = tnum_and(false_reg->var_off, | ||
4033 | tnum_const(~val)); | ||
4034 | if (is_power_of_2(val)) | ||
4035 | true_reg->var_off = tnum_or(true_reg->var_off, | ||
4036 | tnum_const(val)); | ||
4037 | break; | ||
4018 | case BPF_JGT: | 4038 | case BPF_JGT: |
4019 | true_reg->umax_value = min(true_reg->umax_value, val - 1); | 4039 | true_reg->umax_value = min(true_reg->umax_value, val - 1); |
4020 | false_reg->umin_value = max(false_reg->umin_value, val); | 4040 | false_reg->umin_value = max(false_reg->umin_value, val); |
@@ -6963,10 +6983,11 @@ skip_full_check: | |||
6963 | free_states(env); | 6983 | free_states(env); |
6964 | 6984 | ||
6965 | if (ret == 0) | 6985 | if (ret == 0) |
6966 | sanitize_dead_code(env); | 6986 | ret = check_max_stack_depth(env); |
6967 | 6987 | ||
6988 | /* instruction rewrites happen after this point */ | ||
6968 | if (ret == 0) | 6989 | if (ret == 0) |
6969 | ret = check_max_stack_depth(env); | 6990 | sanitize_dead_code(env); |
6970 | 6991 | ||
6971 | if (ret == 0) | 6992 | if (ret == 0) |
6972 | /* program is valid, convert *(u32*)(ctx + off) accesses */ | 6993 | /* program is valid, convert *(u32*)(ctx + off) accesses */ |
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index 1b799e30c06d..4a9785043a39 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore | |||
@@ -27,3 +27,4 @@ test_flow_dissector | |||
27 | flow_dissector_load | 27 | flow_dissector_load |
28 | test_netcnt | 28 | test_netcnt |
29 | test_section_names | 29 | test_section_names |
30 | test_tcpnotify_user | ||
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 7865b94c02c4..b246931c46ef 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #define MAX_INSNS BPF_MAXINSNS | 49 | #define MAX_INSNS BPF_MAXINSNS |
50 | #define MAX_FIXUPS 8 | 50 | #define MAX_FIXUPS 8 |
51 | #define MAX_NR_MAPS 13 | 51 | #define MAX_NR_MAPS 13 |
52 | #define MAX_TEST_RUNS 8 | ||
52 | #define POINTER_VALUE 0xcafe4all | 53 | #define POINTER_VALUE 0xcafe4all |
53 | #define TEST_DATA_LEN 64 | 54 | #define TEST_DATA_LEN 64 |
54 | 55 | ||
@@ -86,6 +87,14 @@ struct bpf_test { | |||
86 | uint8_t flags; | 87 | uint8_t flags; |
87 | __u8 data[TEST_DATA_LEN]; | 88 | __u8 data[TEST_DATA_LEN]; |
88 | void (*fill_helper)(struct bpf_test *self); | 89 | void (*fill_helper)(struct bpf_test *self); |
90 | uint8_t runs; | ||
91 | struct { | ||
92 | uint32_t retval, retval_unpriv; | ||
93 | union { | ||
94 | __u8 data[TEST_DATA_LEN]; | ||
95 | __u64 data64[TEST_DATA_LEN / 8]; | ||
96 | }; | ||
97 | } retvals[MAX_TEST_RUNS]; | ||
89 | }; | 98 | }; |
90 | 99 | ||
91 | /* Note we want this to be 64 bit aligned so that the end of our array is | 100 | /* Note we want this to be 64 bit aligned so that the end of our array is |
@@ -14161,6 +14170,197 @@ static struct bpf_test tests[] = { | |||
14161 | .errstr_unpriv = "R1 leaks addr", | 14170 | .errstr_unpriv = "R1 leaks addr", |
14162 | .result = REJECT, | 14171 | .result = REJECT, |
14163 | }, | 14172 | }, |
14173 | { | ||
14174 | "jset: functional", | ||
14175 | .insns = { | ||
14176 | /* r0 = 0 */ | ||
14177 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
14178 | /* prep for direct packet access via r2 */ | ||
14179 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | ||
14180 | offsetof(struct __sk_buff, data)), | ||
14181 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||
14182 | offsetof(struct __sk_buff, data_end)), | ||
14183 | BPF_MOV64_REG(BPF_REG_4, BPF_REG_2), | ||
14184 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8), | ||
14185 | BPF_JMP_REG(BPF_JLE, BPF_REG_4, BPF_REG_3, 1), | ||
14186 | BPF_EXIT_INSN(), | ||
14187 | |||
14188 | BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_2, 0), | ||
14189 | |||
14190 | /* reg, bit 63 or bit 0 set, taken */ | ||
14191 | BPF_LD_IMM64(BPF_REG_8, 0x8000000000000001), | ||
14192 | BPF_JMP_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1), | ||
14193 | BPF_EXIT_INSN(), | ||
14194 | |||
14195 | /* reg, bit 62, not taken */ | ||
14196 | BPF_LD_IMM64(BPF_REG_8, 0x4000000000000000), | ||
14197 | BPF_JMP_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1), | ||
14198 | BPF_JMP_IMM(BPF_JA, 0, 0, 1), | ||
14199 | BPF_EXIT_INSN(), | ||
14200 | |||
14201 | /* imm, any bit set, taken */ | ||
14202 | BPF_JMP_IMM(BPF_JSET, BPF_REG_7, -1, 1), | ||
14203 | BPF_EXIT_INSN(), | ||
14204 | |||
14205 | /* imm, bit 31 set, taken */ | ||
14206 | BPF_JMP_IMM(BPF_JSET, BPF_REG_7, 0x80000000, 1), | ||
14207 | BPF_EXIT_INSN(), | ||
14208 | |||
14209 | /* all good - return r0 == 2 */ | ||
14210 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
14211 | BPF_EXIT_INSN(), | ||
14212 | }, | ||
14213 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
14214 | .result = ACCEPT, | ||
14215 | .runs = 7, | ||
14216 | .retvals = { | ||
14217 | { .retval = 2, | ||
14218 | .data64 = { (1ULL << 63) | (1U << 31) | (1U << 0), } | ||
14219 | }, | ||
14220 | { .retval = 2, | ||
14221 | .data64 = { (1ULL << 63) | (1U << 31), } | ||
14222 | }, | ||
14223 | { .retval = 2, | ||
14224 | .data64 = { (1ULL << 31) | (1U << 0), } | ||
14225 | }, | ||
14226 | { .retval = 2, | ||
14227 | .data64 = { (__u32)-1, } | ||
14228 | }, | ||
14229 | { .retval = 2, | ||
14230 | .data64 = { ~0x4000000000000000ULL, } | ||
14231 | }, | ||
14232 | { .retval = 0, | ||
14233 | .data64 = { 0, } | ||
14234 | }, | ||
14235 | { .retval = 0, | ||
14236 | .data64 = { ~0ULL, } | ||
14237 | }, | ||
14238 | }, | ||
14239 | }, | ||
14240 | { | ||
14241 | "jset: sign-extend", | ||
14242 | .insns = { | ||
14243 | /* r0 = 0 */ | ||
14244 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
14245 | /* prep for direct packet access via r2 */ | ||
14246 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | ||
14247 | offsetof(struct __sk_buff, data)), | ||
14248 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||
14249 | offsetof(struct __sk_buff, data_end)), | ||
14250 | BPF_MOV64_REG(BPF_REG_4, BPF_REG_2), | ||
14251 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8), | ||
14252 | BPF_JMP_REG(BPF_JLE, BPF_REG_4, BPF_REG_3, 1), | ||
14253 | BPF_EXIT_INSN(), | ||
14254 | |||
14255 | BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_2, 0), | ||
14256 | |||
14257 | BPF_JMP_IMM(BPF_JSET, BPF_REG_7, 0x80000000, 1), | ||
14258 | BPF_EXIT_INSN(), | ||
14259 | |||
14260 | BPF_MOV64_IMM(BPF_REG_0, 2), | ||
14261 | BPF_EXIT_INSN(), | ||
14262 | }, | ||
14263 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
14264 | .result = ACCEPT, | ||
14265 | .retval = 2, | ||
14266 | .data = { 1, 0, 0, 0, 0, 0, 0, 1, }, | ||
14267 | }, | ||
14268 | { | ||
14269 | "jset: known const compare", | ||
14270 | .insns = { | ||
14271 | BPF_MOV64_IMM(BPF_REG_0, 1), | ||
14272 | BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1), | ||
14273 | BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), | ||
14274 | BPF_EXIT_INSN(), | ||
14275 | }, | ||
14276 | .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
14277 | .retval_unpriv = 1, | ||
14278 | .result_unpriv = ACCEPT, | ||
14279 | .retval = 1, | ||
14280 | .result = ACCEPT, | ||
14281 | }, | ||
14282 | { | ||
14283 | "jset: known const compare bad", | ||
14284 | .insns = { | ||
14285 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
14286 | BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1), | ||
14287 | BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), | ||
14288 | BPF_EXIT_INSN(), | ||
14289 | }, | ||
14290 | .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
14291 | .errstr_unpriv = "!read_ok", | ||
14292 | .result_unpriv = REJECT, | ||
14293 | .errstr = "!read_ok", | ||
14294 | .result = REJECT, | ||
14295 | }, | ||
14296 | { | ||
14297 | "jset: unknown const compare taken", | ||
14298 | .insns = { | ||
14299 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
14300 | BPF_FUNC_get_prandom_u32), | ||
14301 | BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1), | ||
14302 | BPF_JMP_IMM(BPF_JA, 0, 0, 1), | ||
14303 | BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), | ||
14304 | BPF_EXIT_INSN(), | ||
14305 | }, | ||
14306 | .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
14307 | .errstr_unpriv = "!read_ok", | ||
14308 | .result_unpriv = REJECT, | ||
14309 | .errstr = "!read_ok", | ||
14310 | .result = REJECT, | ||
14311 | }, | ||
14312 | { | ||
14313 | "jset: unknown const compare not taken", | ||
14314 | .insns = { | ||
14315 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
14316 | BPF_FUNC_get_prandom_u32), | ||
14317 | BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1), | ||
14318 | BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), | ||
14319 | BPF_EXIT_INSN(), | ||
14320 | }, | ||
14321 | .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
14322 | .errstr_unpriv = "!read_ok", | ||
14323 | .result_unpriv = REJECT, | ||
14324 | .errstr = "!read_ok", | ||
14325 | .result = REJECT, | ||
14326 | }, | ||
14327 | { | ||
14328 | "jset: half-known const compare", | ||
14329 | .insns = { | ||
14330 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
14331 | BPF_FUNC_get_prandom_u32), | ||
14332 | BPF_ALU64_IMM(BPF_OR, BPF_REG_0, 2), | ||
14333 | BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 3, 1), | ||
14334 | BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), | ||
14335 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
14336 | BPF_EXIT_INSN(), | ||
14337 | }, | ||
14338 | .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
14339 | .result_unpriv = ACCEPT, | ||
14340 | .result = ACCEPT, | ||
14341 | }, | ||
14342 | { | ||
14343 | "jset: range", | ||
14344 | .insns = { | ||
14345 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
14346 | BPF_FUNC_get_prandom_u32), | ||
14347 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), | ||
14348 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
14349 | BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xff), | ||
14350 | BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0xf0, 3), | ||
14351 | BPF_JMP_IMM(BPF_JLT, BPF_REG_1, 0x10, 1), | ||
14352 | BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), | ||
14353 | BPF_EXIT_INSN(), | ||
14354 | BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0x10, 1), | ||
14355 | BPF_EXIT_INSN(), | ||
14356 | BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0x10, 1), | ||
14357 | BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0), | ||
14358 | BPF_EXIT_INSN(), | ||
14359 | }, | ||
14360 | .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, | ||
14361 | .result_unpriv = ACCEPT, | ||
14362 | .result = ACCEPT, | ||
14363 | }, | ||
14164 | }; | 14364 | }; |
14165 | 14365 | ||
14166 | static int probe_filter_length(const struct bpf_insn *fp) | 14366 | static int probe_filter_length(const struct bpf_insn *fp) |
@@ -14443,16 +14643,42 @@ out: | |||
14443 | return ret; | 14643 | return ret; |
14444 | } | 14644 | } |
14445 | 14645 | ||
14646 | static int do_prog_test_run(int fd_prog, bool unpriv, uint32_t expected_val, | ||
14647 | void *data, size_t size_data) | ||
14648 | { | ||
14649 | __u8 tmp[TEST_DATA_LEN << 2]; | ||
14650 | __u32 size_tmp = sizeof(tmp); | ||
14651 | uint32_t retval; | ||
14652 | int err; | ||
14653 | |||
14654 | if (unpriv) | ||
14655 | set_admin(true); | ||
14656 | err = bpf_prog_test_run(fd_prog, 1, data, size_data, | ||
14657 | tmp, &size_tmp, &retval, NULL); | ||
14658 | if (unpriv) | ||
14659 | set_admin(false); | ||
14660 | if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { | ||
14661 | printf("Unexpected bpf_prog_test_run error "); | ||
14662 | return err; | ||
14663 | } | ||
14664 | if (!err && retval != expected_val && | ||
14665 | expected_val != POINTER_VALUE) { | ||
14666 | printf("FAIL retval %d != %d ", retval, expected_val); | ||
14667 | return 1; | ||
14668 | } | ||
14669 | |||
14670 | return 0; | ||
14671 | } | ||
14672 | |||
14446 | static void do_test_single(struct bpf_test *test, bool unpriv, | 14673 | static void do_test_single(struct bpf_test *test, bool unpriv, |
14447 | int *passes, int *errors) | 14674 | int *passes, int *errors) |
14448 | { | 14675 | { |
14449 | int fd_prog, expected_ret, alignment_prevented_execution; | 14676 | int fd_prog, expected_ret, alignment_prevented_execution; |
14450 | int prog_len, prog_type = test->prog_type; | 14677 | int prog_len, prog_type = test->prog_type; |
14451 | struct bpf_insn *prog = test->insns; | 14678 | struct bpf_insn *prog = test->insns; |
14679 | int run_errs, run_successes; | ||
14452 | int map_fds[MAX_NR_MAPS]; | 14680 | int map_fds[MAX_NR_MAPS]; |
14453 | const char *expected_err; | 14681 | const char *expected_err; |
14454 | uint32_t expected_val; | ||
14455 | uint32_t retval; | ||
14456 | __u32 pflags; | 14682 | __u32 pflags; |
14457 | int i, err; | 14683 | int i, err; |
14458 | 14684 | ||
@@ -14476,8 +14702,6 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
14476 | test->result_unpriv : test->result; | 14702 | test->result_unpriv : test->result; |
14477 | expected_err = unpriv && test->errstr_unpriv ? | 14703 | expected_err = unpriv && test->errstr_unpriv ? |
14478 | test->errstr_unpriv : test->errstr; | 14704 | test->errstr_unpriv : test->errstr; |
14479 | expected_val = unpriv && test->retval_unpriv ? | ||
14480 | test->retval_unpriv : test->retval; | ||
14481 | 14705 | ||
14482 | alignment_prevented_execution = 0; | 14706 | alignment_prevented_execution = 0; |
14483 | 14707 | ||
@@ -14489,10 +14713,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
14489 | } | 14713 | } |
14490 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | 14714 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
14491 | if (fd_prog >= 0 && | 14715 | if (fd_prog >= 0 && |
14492 | (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS)) { | 14716 | (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS)) |
14493 | alignment_prevented_execution = 1; | 14717 | alignment_prevented_execution = 1; |
14494 | goto test_ok; | ||
14495 | } | ||
14496 | #endif | 14718 | #endif |
14497 | } else { | 14719 | } else { |
14498 | if (fd_prog >= 0) { | 14720 | if (fd_prog >= 0) { |
@@ -14519,33 +14741,54 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
14519 | } | 14741 | } |
14520 | } | 14742 | } |
14521 | 14743 | ||
14522 | if (fd_prog >= 0) { | 14744 | run_errs = 0; |
14523 | __u8 tmp[TEST_DATA_LEN << 2]; | 14745 | run_successes = 0; |
14524 | __u32 size_tmp = sizeof(tmp); | 14746 | if (!alignment_prevented_execution && fd_prog >= 0) { |
14525 | 14747 | uint32_t expected_val; | |
14526 | if (unpriv) | 14748 | int i; |
14527 | set_admin(true); | 14749 | |
14528 | err = bpf_prog_test_run(fd_prog, 1, test->data, | 14750 | if (!test->runs) { |
14529 | sizeof(test->data), tmp, &size_tmp, | 14751 | expected_val = unpriv && test->retval_unpriv ? |
14530 | &retval, NULL); | 14752 | test->retval_unpriv : test->retval; |
14531 | if (unpriv) | 14753 | |
14532 | set_admin(false); | 14754 | err = do_prog_test_run(fd_prog, unpriv, expected_val, |
14533 | if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { | 14755 | test->data, sizeof(test->data)); |
14534 | printf("Unexpected bpf_prog_test_run error\n"); | 14756 | if (err) |
14535 | goto fail_log; | 14757 | run_errs++; |
14758 | else | ||
14759 | run_successes++; | ||
14536 | } | 14760 | } |
14537 | if (!err && retval != expected_val && | 14761 | |
14538 | expected_val != POINTER_VALUE) { | 14762 | for (i = 0; i < test->runs; i++) { |
14539 | printf("FAIL retval %d != %d\n", retval, expected_val); | 14763 | if (unpriv && test->retvals[i].retval_unpriv) |
14540 | goto fail_log; | 14764 | expected_val = test->retvals[i].retval_unpriv; |
14765 | else | ||
14766 | expected_val = test->retvals[i].retval; | ||
14767 | |||
14768 | err = do_prog_test_run(fd_prog, unpriv, expected_val, | ||
14769 | test->retvals[i].data, | ||
14770 | sizeof(test->retvals[i].data)); | ||
14771 | if (err) { | ||
14772 | printf("(run %d/%d) ", i + 1, test->runs); | ||
14773 | run_errs++; | ||
14774 | } else { | ||
14775 | run_successes++; | ||
14776 | } | ||
14541 | } | 14777 | } |
14542 | } | 14778 | } |
14543 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | 14779 | |
14544 | test_ok: | 14780 | if (!run_errs) { |
14545 | #endif | 14781 | (*passes)++; |
14546 | (*passes)++; | 14782 | if (run_successes > 1) |
14547 | printf("OK%s\n", alignment_prevented_execution ? | 14783 | printf("%d cases ", run_successes); |
14548 | " (NOTE: not executed due to unknown alignment)" : ""); | 14784 | printf("OK"); |
14785 | if (alignment_prevented_execution) | ||
14786 | printf(" (NOTE: not executed due to unknown alignment)"); | ||
14787 | printf("\n"); | ||
14788 | } else { | ||
14789 | printf("\n"); | ||
14790 | goto fail_log; | ||
14791 | } | ||
14549 | close_fds: | 14792 | close_fds: |
14550 | close(fd_prog); | 14793 | close(fd_prog); |
14551 | for (i = 0; i < MAX_NR_MAPS; i++) | 14794 | for (i = 0; i < MAX_NR_MAPS; i++) |