diff options
| -rw-r--r-- | include/linux/filter.h | 10 | ||||
| -rw-r--r-- | tools/include/linux/filter.h | 10 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 239 |
3 files changed, 255 insertions, 4 deletions
diff --git a/include/linux/filter.h b/include/linux/filter.h index 56197f82af45..62d948f80730 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h | |||
| @@ -272,6 +272,16 @@ struct bpf_prog_aux; | |||
| 272 | .off = OFF, \ | 272 | .off = OFF, \ |
| 273 | .imm = IMM }) | 273 | .imm = IMM }) |
| 274 | 274 | ||
| 275 | /* Unconditional jumps, goto pc + off16 */ | ||
| 276 | |||
| 277 | #define BPF_JMP_A(OFF) \ | ||
| 278 | ((struct bpf_insn) { \ | ||
| 279 | .code = BPF_JMP | BPF_JA, \ | ||
| 280 | .dst_reg = 0, \ | ||
| 281 | .src_reg = 0, \ | ||
| 282 | .off = OFF, \ | ||
| 283 | .imm = 0 }) | ||
| 284 | |||
| 275 | /* Function call */ | 285 | /* Function call */ |
| 276 | 286 | ||
| 277 | #define BPF_EMIT_CALL(FUNC) \ | 287 | #define BPF_EMIT_CALL(FUNC) \ |
diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h index 390d7c9685fd..4ce25d43e8e3 100644 --- a/tools/include/linux/filter.h +++ b/tools/include/linux/filter.h | |||
| @@ -208,6 +208,16 @@ | |||
| 208 | .off = OFF, \ | 208 | .off = OFF, \ |
| 209 | .imm = IMM }) | 209 | .imm = IMM }) |
| 210 | 210 | ||
| 211 | /* Unconditional jumps, goto pc + off16 */ | ||
| 212 | |||
| 213 | #define BPF_JMP_A(OFF) \ | ||
| 214 | ((struct bpf_insn) { \ | ||
| 215 | .code = BPF_JMP | BPF_JA, \ | ||
| 216 | .dst_reg = 0, \ | ||
| 217 | .src_reg = 0, \ | ||
| 218 | .off = OFF, \ | ||
| 219 | .imm = 0 }) | ||
| 220 | |||
| 211 | /* Function call */ | 221 | /* Function call */ |
| 212 | 222 | ||
| 213 | #define BPF_EMIT_CALL(FUNC) \ | 223 | #define BPF_EMIT_CALL(FUNC) \ |
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 3773562056da..cabb19b1e371 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #define MAX_NR_MAPS 4 | 49 | #define MAX_NR_MAPS 4 |
| 50 | 50 | ||
| 51 | #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) | 51 | #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) |
| 52 | #define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) | ||
| 52 | 53 | ||
| 53 | struct bpf_test { | 54 | struct bpf_test { |
| 54 | const char *descr; | 55 | const char *descr; |
| @@ -2615,6 +2616,30 @@ static struct bpf_test tests[] = { | |||
| 2615 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 2616 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 2616 | }, | 2617 | }, |
| 2617 | { | 2618 | { |
| 2619 | "direct packet access: test17 (pruning, alignment)", | ||
| 2620 | .insns = { | ||
| 2621 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | ||
| 2622 | offsetof(struct __sk_buff, data)), | ||
| 2623 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | ||
| 2624 | offsetof(struct __sk_buff, data_end)), | ||
| 2625 | BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, | ||
| 2626 | offsetof(struct __sk_buff, mark)), | ||
| 2627 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), | ||
| 2628 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 14), | ||
| 2629 | BPF_JMP_IMM(BPF_JGT, BPF_REG_7, 1, 4), | ||
| 2630 | BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1), | ||
| 2631 | BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, -4), | ||
| 2632 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
| 2633 | BPF_EXIT_INSN(), | ||
| 2634 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), | ||
| 2635 | BPF_JMP_A(-6), | ||
| 2636 | }, | ||
| 2637 | .errstr = "misaligned packet access off 2+15+-4 size 4", | ||
| 2638 | .result = REJECT, | ||
| 2639 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | ||
| 2640 | .flags = F_LOAD_WITH_STRICT_ALIGNMENT, | ||
| 2641 | }, | ||
| 2642 | { | ||
| 2618 | "helper access to packet: test1, valid packet_ptr range", | 2643 | "helper access to packet: test1, valid packet_ptr range", |
| 2619 | .insns = { | 2644 | .insns = { |
| 2620 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | 2645 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| @@ -3341,6 +3366,70 @@ static struct bpf_test tests[] = { | |||
| 3341 | .prog_type = BPF_PROG_TYPE_SCHED_CLS | 3366 | .prog_type = BPF_PROG_TYPE_SCHED_CLS |
| 3342 | }, | 3367 | }, |
| 3343 | { | 3368 | { |
| 3369 | "alu ops on ptr_to_map_value_or_null, 1", | ||
| 3370 | .insns = { | ||
| 3371 | BPF_MOV64_IMM(BPF_REG_1, 10), | ||
| 3372 | BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), | ||
| 3373 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 3374 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 3375 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 3376 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
| 3377 | BPF_FUNC_map_lookup_elem), | ||
| 3378 | BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), | ||
| 3379 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -2), | ||
| 3380 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2), | ||
| 3381 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), | ||
| 3382 | BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), | ||
| 3383 | BPF_EXIT_INSN(), | ||
| 3384 | }, | ||
| 3385 | .fixup_map1 = { 4 }, | ||
| 3386 | .errstr = "R4 invalid mem access", | ||
| 3387 | .result = REJECT, | ||
| 3388 | .prog_type = BPF_PROG_TYPE_SCHED_CLS | ||
| 3389 | }, | ||
| 3390 | { | ||
| 3391 | "alu ops on ptr_to_map_value_or_null, 2", | ||
| 3392 | .insns = { | ||
| 3393 | BPF_MOV64_IMM(BPF_REG_1, 10), | ||
| 3394 | BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), | ||
| 3395 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 3396 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 3397 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 3398 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
| 3399 | BPF_FUNC_map_lookup_elem), | ||
| 3400 | BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), | ||
| 3401 | BPF_ALU64_IMM(BPF_AND, BPF_REG_4, -1), | ||
| 3402 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), | ||
| 3403 | BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), | ||
| 3404 | BPF_EXIT_INSN(), | ||
| 3405 | }, | ||
| 3406 | .fixup_map1 = { 4 }, | ||
| 3407 | .errstr = "R4 invalid mem access", | ||
| 3408 | .result = REJECT, | ||
| 3409 | .prog_type = BPF_PROG_TYPE_SCHED_CLS | ||
| 3410 | }, | ||
| 3411 | { | ||
| 3412 | "alu ops on ptr_to_map_value_or_null, 3", | ||
| 3413 | .insns = { | ||
| 3414 | BPF_MOV64_IMM(BPF_REG_1, 10), | ||
| 3415 | BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8), | ||
| 3416 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 3417 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 3418 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 3419 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | ||
| 3420 | BPF_FUNC_map_lookup_elem), | ||
| 3421 | BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), | ||
| 3422 | BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 1), | ||
| 3423 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), | ||
| 3424 | BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), | ||
| 3425 | BPF_EXIT_INSN(), | ||
| 3426 | }, | ||
| 3427 | .fixup_map1 = { 4 }, | ||
| 3428 | .errstr = "R4 invalid mem access", | ||
| 3429 | .result = REJECT, | ||
| 3430 | .prog_type = BPF_PROG_TYPE_SCHED_CLS | ||
| 3431 | }, | ||
| 3432 | { | ||
| 3344 | "invalid memory access with multiple map_lookup_elem calls", | 3433 | "invalid memory access with multiple map_lookup_elem calls", |
| 3345 | .insns = { | 3434 | .insns = { |
| 3346 | BPF_MOV64_IMM(BPF_REG_1, 10), | 3435 | BPF_MOV64_IMM(BPF_REG_1, 10), |
| @@ -4937,7 +5026,149 @@ static struct bpf_test tests[] = { | |||
| 4937 | .fixup_map_in_map = { 3 }, | 5026 | .fixup_map_in_map = { 3 }, |
| 4938 | .errstr = "R1 type=map_value_or_null expected=map_ptr", | 5027 | .errstr = "R1 type=map_value_or_null expected=map_ptr", |
| 4939 | .result = REJECT, | 5028 | .result = REJECT, |
| 4940 | } | 5029 | }, |
| 5030 | { | ||
| 5031 | "ld_abs: check calling conv, r1", | ||
| 5032 | .insns = { | ||
| 5033 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5034 | BPF_MOV64_IMM(BPF_REG_1, 0), | ||
| 5035 | BPF_LD_ABS(BPF_W, -0x200000), | ||
| 5036 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), | ||
| 5037 | BPF_EXIT_INSN(), | ||
| 5038 | }, | ||
| 5039 | .errstr = "R1 !read_ok", | ||
| 5040 | .result = REJECT, | ||
| 5041 | }, | ||
| 5042 | { | ||
| 5043 | "ld_abs: check calling conv, r2", | ||
| 5044 | .insns = { | ||
| 5045 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5046 | BPF_MOV64_IMM(BPF_REG_2, 0), | ||
| 5047 | BPF_LD_ABS(BPF_W, -0x200000), | ||
| 5048 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), | ||
| 5049 | BPF_EXIT_INSN(), | ||
| 5050 | }, | ||
| 5051 | .errstr = "R2 !read_ok", | ||
| 5052 | .result = REJECT, | ||
| 5053 | }, | ||
| 5054 | { | ||
| 5055 | "ld_abs: check calling conv, r3", | ||
| 5056 | .insns = { | ||
| 5057 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5058 | BPF_MOV64_IMM(BPF_REG_3, 0), | ||
| 5059 | BPF_LD_ABS(BPF_W, -0x200000), | ||
| 5060 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_3), | ||
| 5061 | BPF_EXIT_INSN(), | ||
| 5062 | }, | ||
| 5063 | .errstr = "R3 !read_ok", | ||
| 5064 | .result = REJECT, | ||
| 5065 | }, | ||
| 5066 | { | ||
| 5067 | "ld_abs: check calling conv, r4", | ||
| 5068 | .insns = { | ||
| 5069 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5070 | BPF_MOV64_IMM(BPF_REG_4, 0), | ||
| 5071 | BPF_LD_ABS(BPF_W, -0x200000), | ||
| 5072 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_4), | ||
| 5073 | BPF_EXIT_INSN(), | ||
| 5074 | }, | ||
| 5075 | .errstr = "R4 !read_ok", | ||
| 5076 | .result = REJECT, | ||
| 5077 | }, | ||
| 5078 | { | ||
| 5079 | "ld_abs: check calling conv, r5", | ||
| 5080 | .insns = { | ||
| 5081 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5082 | BPF_MOV64_IMM(BPF_REG_5, 0), | ||
| 5083 | BPF_LD_ABS(BPF_W, -0x200000), | ||
| 5084 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_5), | ||
| 5085 | BPF_EXIT_INSN(), | ||
| 5086 | }, | ||
| 5087 | .errstr = "R5 !read_ok", | ||
| 5088 | .result = REJECT, | ||
| 5089 | }, | ||
| 5090 | { | ||
| 5091 | "ld_abs: check calling conv, r7", | ||
| 5092 | .insns = { | ||
| 5093 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5094 | BPF_MOV64_IMM(BPF_REG_7, 0), | ||
| 5095 | BPF_LD_ABS(BPF_W, -0x200000), | ||
| 5096 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), | ||
| 5097 | BPF_EXIT_INSN(), | ||
| 5098 | }, | ||
| 5099 | .result = ACCEPT, | ||
| 5100 | }, | ||
| 5101 | { | ||
| 5102 | "ld_ind: check calling conv, r1", | ||
| 5103 | .insns = { | ||
| 5104 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5105 | BPF_MOV64_IMM(BPF_REG_1, 1), | ||
| 5106 | BPF_LD_IND(BPF_W, BPF_REG_1, -0x200000), | ||
| 5107 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), | ||
| 5108 | BPF_EXIT_INSN(), | ||
| 5109 | }, | ||
| 5110 | .errstr = "R1 !read_ok", | ||
| 5111 | .result = REJECT, | ||
| 5112 | }, | ||
| 5113 | { | ||
| 5114 | "ld_ind: check calling conv, r2", | ||
| 5115 | .insns = { | ||
| 5116 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5117 | BPF_MOV64_IMM(BPF_REG_2, 1), | ||
| 5118 | BPF_LD_IND(BPF_W, BPF_REG_2, -0x200000), | ||
| 5119 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), | ||
| 5120 | BPF_EXIT_INSN(), | ||
| 5121 | }, | ||
| 5122 | .errstr = "R2 !read_ok", | ||
| 5123 | .result = REJECT, | ||
| 5124 | }, | ||
| 5125 | { | ||
| 5126 | "ld_ind: check calling conv, r3", | ||
| 5127 | .insns = { | ||
| 5128 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5129 | BPF_MOV64_IMM(BPF_REG_3, 1), | ||
| 5130 | BPF_LD_IND(BPF_W, BPF_REG_3, -0x200000), | ||
| 5131 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_3), | ||
| 5132 | BPF_EXIT_INSN(), | ||
| 5133 | }, | ||
| 5134 | .errstr = "R3 !read_ok", | ||
| 5135 | .result = REJECT, | ||
| 5136 | }, | ||
| 5137 | { | ||
| 5138 | "ld_ind: check calling conv, r4", | ||
| 5139 | .insns = { | ||
| 5140 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5141 | BPF_MOV64_IMM(BPF_REG_4, 1), | ||
| 5142 | BPF_LD_IND(BPF_W, BPF_REG_4, -0x200000), | ||
| 5143 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_4), | ||
| 5144 | BPF_EXIT_INSN(), | ||
| 5145 | }, | ||
| 5146 | .errstr = "R4 !read_ok", | ||
| 5147 | .result = REJECT, | ||
| 5148 | }, | ||
| 5149 | { | ||
| 5150 | "ld_ind: check calling conv, r5", | ||
| 5151 | .insns = { | ||
| 5152 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5153 | BPF_MOV64_IMM(BPF_REG_5, 1), | ||
| 5154 | BPF_LD_IND(BPF_W, BPF_REG_5, -0x200000), | ||
| 5155 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_5), | ||
| 5156 | BPF_EXIT_INSN(), | ||
| 5157 | }, | ||
| 5158 | .errstr = "R5 !read_ok", | ||
| 5159 | .result = REJECT, | ||
| 5160 | }, | ||
| 5161 | { | ||
| 5162 | "ld_ind: check calling conv, r7", | ||
| 5163 | .insns = { | ||
| 5164 | BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), | ||
| 5165 | BPF_MOV64_IMM(BPF_REG_7, 1), | ||
| 5166 | BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000), | ||
| 5167 | BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), | ||
| 5168 | BPF_EXIT_INSN(), | ||
| 5169 | }, | ||
| 5170 | .result = ACCEPT, | ||
| 5171 | }, | ||
| 4941 | }; | 5172 | }; |
| 4942 | 5173 | ||
| 4943 | static int probe_filter_length(const struct bpf_insn *fp) | 5174 | static int probe_filter_length(const struct bpf_insn *fp) |
| @@ -5059,9 +5290,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
| 5059 | 5290 | ||
| 5060 | do_test_fixup(test, prog, map_fds); | 5291 | do_test_fixup(test, prog, map_fds); |
| 5061 | 5292 | ||
| 5062 | fd_prog = bpf_load_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, | 5293 | fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, |
| 5063 | prog, prog_len, "GPL", 0, bpf_vlog, | 5294 | prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT, |
| 5064 | sizeof(bpf_vlog)); | 5295 | "GPL", 0, bpf_vlog, sizeof(bpf_vlog)); |
| 5065 | 5296 | ||
| 5066 | expected_ret = unpriv && test->result_unpriv != UNDEF ? | 5297 | expected_ret = unpriv && test->result_unpriv != UNDEF ? |
| 5067 | test->result_unpriv : test->result; | 5298 | test->result_unpriv : test->result; |
