diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-01-18 16:38:59 -0500 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-01-18 16:39:40 -0500 |
commit | 0c91c4239d23d44a5cb95f51e9d4b71d88793d75 (patch) | |
tree | 7ca9af66f490c3d959c3c6e9042bf86b1c513563 /tools | |
parent | e7b2823a582a5bca5ee47644f448e317178e8824 (diff) | |
parent | 111e6b45315c8d13658f23885b30eb9df3ea2914 (diff) |
Merge branch 'bpf-improve-test-verifier-coverage'
Alexei Starovoitov says:
====================
BPF verifier has 700+ tests used to check correctness of the verifier.
Beyond checking the verifier log tell kernel to run accepted programs
as well via bpf_prog_test_run() command. That improves quality of the
tests and increases bpf test coverage.
====================
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 960179882a1c..6c22edb1f006 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/filter.h> | 29 | #include <linux/filter.h> |
30 | #include <linux/bpf_perf_event.h> | 30 | #include <linux/bpf_perf_event.h> |
31 | #include <linux/bpf.h> | 31 | #include <linux/bpf.h> |
32 | #include <linux/if_ether.h> | ||
32 | 33 | ||
33 | #include <bpf/bpf.h> | 34 | #include <bpf/bpf.h> |
34 | 35 | ||
@@ -49,6 +50,8 @@ | |||
49 | #define MAX_INSNS 512 | 50 | #define MAX_INSNS 512 |
50 | #define MAX_FIXUPS 8 | 51 | #define MAX_FIXUPS 8 |
51 | #define MAX_NR_MAPS 4 | 52 | #define MAX_NR_MAPS 4 |
53 | #define POINTER_VALUE 0xcafe4all | ||
54 | #define TEST_DATA_LEN 64 | ||
52 | 55 | ||
53 | #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) | 56 | #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS (1 << 0) |
54 | #define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) | 57 | #define F_LOAD_WITH_STRICT_ALIGNMENT (1 << 1) |
@@ -62,6 +65,7 @@ struct bpf_test { | |||
62 | int fixup_map_in_map[MAX_FIXUPS]; | 65 | int fixup_map_in_map[MAX_FIXUPS]; |
63 | const char *errstr; | 66 | const char *errstr; |
64 | const char *errstr_unpriv; | 67 | const char *errstr_unpriv; |
68 | uint32_t retval; | ||
65 | enum { | 69 | enum { |
66 | UNDEF, | 70 | UNDEF, |
67 | ACCEPT, | 71 | ACCEPT, |
@@ -95,6 +99,7 @@ static struct bpf_test tests[] = { | |||
95 | BPF_EXIT_INSN(), | 99 | BPF_EXIT_INSN(), |
96 | }, | 100 | }, |
97 | .result = ACCEPT, | 101 | .result = ACCEPT, |
102 | .retval = -3, | ||
98 | }, | 103 | }, |
99 | { | 104 | { |
100 | "unreachable", | 105 | "unreachable", |
@@ -210,6 +215,7 @@ static struct bpf_test tests[] = { | |||
210 | BPF_EXIT_INSN(), | 215 | BPF_EXIT_INSN(), |
211 | }, | 216 | }, |
212 | .result = ACCEPT, | 217 | .result = ACCEPT, |
218 | .retval = 1, | ||
213 | }, | 219 | }, |
214 | { | 220 | { |
215 | "test8 ld_imm64", | 221 | "test8 ld_imm64", |
@@ -517,6 +523,7 @@ static struct bpf_test tests[] = { | |||
517 | .errstr_unpriv = "R0 leaks addr", | 523 | .errstr_unpriv = "R0 leaks addr", |
518 | .result = ACCEPT, | 524 | .result = ACCEPT, |
519 | .result_unpriv = REJECT, | 525 | .result_unpriv = REJECT, |
526 | .retval = POINTER_VALUE, | ||
520 | }, | 527 | }, |
521 | { | 528 | { |
522 | "check valid spill/fill, skb mark", | 529 | "check valid spill/fill, skb mark", |
@@ -803,6 +810,7 @@ static struct bpf_test tests[] = { | |||
803 | .errstr_unpriv = "R1 pointer comparison", | 810 | .errstr_unpriv = "R1 pointer comparison", |
804 | .result_unpriv = REJECT, | 811 | .result_unpriv = REJECT, |
805 | .result = ACCEPT, | 812 | .result = ACCEPT, |
813 | .retval = -ENOENT, | ||
806 | }, | 814 | }, |
807 | { | 815 | { |
808 | "jump test 4", | 816 | "jump test 4", |
@@ -1823,6 +1831,7 @@ static struct bpf_test tests[] = { | |||
1823 | BPF_EXIT_INSN(), | 1831 | BPF_EXIT_INSN(), |
1824 | }, | 1832 | }, |
1825 | .result = ACCEPT, | 1833 | .result = ACCEPT, |
1834 | .retval = 0xfaceb00c, | ||
1826 | }, | 1835 | }, |
1827 | { | 1836 | { |
1828 | "PTR_TO_STACK store/load - bad alignment on off", | 1837 | "PTR_TO_STACK store/load - bad alignment on off", |
@@ -1881,6 +1890,7 @@ static struct bpf_test tests[] = { | |||
1881 | .result = ACCEPT, | 1890 | .result = ACCEPT, |
1882 | .result_unpriv = REJECT, | 1891 | .result_unpriv = REJECT, |
1883 | .errstr_unpriv = "R0 leaks addr", | 1892 | .errstr_unpriv = "R0 leaks addr", |
1893 | .retval = POINTER_VALUE, | ||
1884 | }, | 1894 | }, |
1885 | { | 1895 | { |
1886 | "unpriv: add const to pointer", | 1896 | "unpriv: add const to pointer", |
@@ -2054,6 +2064,7 @@ static struct bpf_test tests[] = { | |||
2054 | BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0), | 2064 | BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0), |
2055 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, | 2065 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, |
2056 | BPF_FUNC_get_hash_recalc), | 2066 | BPF_FUNC_get_hash_recalc), |
2067 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
2057 | BPF_EXIT_INSN(), | 2068 | BPF_EXIT_INSN(), |
2058 | }, | 2069 | }, |
2059 | .result = ACCEPT, | 2070 | .result = ACCEPT, |
@@ -2818,6 +2829,7 @@ static struct bpf_test tests[] = { | |||
2818 | }, | 2829 | }, |
2819 | .result = ACCEPT, | 2830 | .result = ACCEPT, |
2820 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 2831 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
2832 | .retval = 1, | ||
2821 | }, | 2833 | }, |
2822 | { | 2834 | { |
2823 | "direct packet access: test12 (and, good access)", | 2835 | "direct packet access: test12 (and, good access)", |
@@ -2842,6 +2854,7 @@ static struct bpf_test tests[] = { | |||
2842 | }, | 2854 | }, |
2843 | .result = ACCEPT, | 2855 | .result = ACCEPT, |
2844 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 2856 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
2857 | .retval = 1, | ||
2845 | }, | 2858 | }, |
2846 | { | 2859 | { |
2847 | "direct packet access: test13 (branches, good access)", | 2860 | "direct packet access: test13 (branches, good access)", |
@@ -2872,6 +2885,7 @@ static struct bpf_test tests[] = { | |||
2872 | }, | 2885 | }, |
2873 | .result = ACCEPT, | 2886 | .result = ACCEPT, |
2874 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 2887 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
2888 | .retval = 1, | ||
2875 | }, | 2889 | }, |
2876 | { | 2890 | { |
2877 | "direct packet access: test14 (pkt_ptr += 0, CONST_IMM, good access)", | 2891 | "direct packet access: test14 (pkt_ptr += 0, CONST_IMM, good access)", |
@@ -2895,6 +2909,7 @@ static struct bpf_test tests[] = { | |||
2895 | }, | 2909 | }, |
2896 | .result = ACCEPT, | 2910 | .result = ACCEPT, |
2897 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 2911 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
2912 | .retval = 1, | ||
2898 | }, | 2913 | }, |
2899 | { | 2914 | { |
2900 | "direct packet access: test15 (spill with xadd)", | 2915 | "direct packet access: test15 (spill with xadd)", |
@@ -3181,6 +3196,7 @@ static struct bpf_test tests[] = { | |||
3181 | }, | 3196 | }, |
3182 | .result = ACCEPT, | 3197 | .result = ACCEPT, |
3183 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 3198 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
3199 | .retval = 1, | ||
3184 | }, | 3200 | }, |
3185 | { | 3201 | { |
3186 | "direct packet access: test28 (marking on <=, bad access)", | 3202 | "direct packet access: test28 (marking on <=, bad access)", |
@@ -5798,6 +5814,7 @@ static struct bpf_test tests[] = { | |||
5798 | }, | 5814 | }, |
5799 | .result = ACCEPT, | 5815 | .result = ACCEPT, |
5800 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 5816 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
5817 | .retval = 0 /* csum_diff of 64-byte packet */, | ||
5801 | }, | 5818 | }, |
5802 | { | 5819 | { |
5803 | "helper access to variable memory: size = 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)", | 5820 | "helper access to variable memory: size = 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)", |
@@ -6166,6 +6183,7 @@ static struct bpf_test tests[] = { | |||
6166 | }, | 6183 | }, |
6167 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 6184 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
6168 | .result = ACCEPT, | 6185 | .result = ACCEPT, |
6186 | .retval = 42 /* ultimate return value */, | ||
6169 | }, | 6187 | }, |
6170 | { | 6188 | { |
6171 | "ld_ind: check calling conv, r1", | 6189 | "ld_ind: check calling conv, r1", |
@@ -6237,6 +6255,7 @@ static struct bpf_test tests[] = { | |||
6237 | BPF_EXIT_INSN(), | 6255 | BPF_EXIT_INSN(), |
6238 | }, | 6256 | }, |
6239 | .result = ACCEPT, | 6257 | .result = ACCEPT, |
6258 | .retval = 1, | ||
6240 | }, | 6259 | }, |
6241 | { | 6260 | { |
6242 | "check bpf_perf_event_data->sample_period byte load permitted", | 6261 | "check bpf_perf_event_data->sample_period byte load permitted", |
@@ -7224,6 +7243,7 @@ static struct bpf_test tests[] = { | |||
7224 | }, | 7243 | }, |
7225 | .fixup_map1 = { 3 }, | 7244 | .fixup_map1 = { 3 }, |
7226 | .result = ACCEPT, | 7245 | .result = ACCEPT, |
7246 | .retval = POINTER_VALUE, | ||
7227 | .result_unpriv = REJECT, | 7247 | .result_unpriv = REJECT, |
7228 | .errstr_unpriv = "R0 leaks addr as return value" | 7248 | .errstr_unpriv = "R0 leaks addr as return value" |
7229 | }, | 7249 | }, |
@@ -7244,6 +7264,7 @@ static struct bpf_test tests[] = { | |||
7244 | }, | 7264 | }, |
7245 | .fixup_map1 = { 3 }, | 7265 | .fixup_map1 = { 3 }, |
7246 | .result = ACCEPT, | 7266 | .result = ACCEPT, |
7267 | .retval = POINTER_VALUE, | ||
7247 | .result_unpriv = REJECT, | 7268 | .result_unpriv = REJECT, |
7248 | .errstr_unpriv = "R0 leaks addr as return value" | 7269 | .errstr_unpriv = "R0 leaks addr as return value" |
7249 | }, | 7270 | }, |
@@ -7685,6 +7706,7 @@ static struct bpf_test tests[] = { | |||
7685 | BPF_EXIT_INSN(), | 7706 | BPF_EXIT_INSN(), |
7686 | }, | 7707 | }, |
7687 | .result = ACCEPT, | 7708 | .result = ACCEPT, |
7709 | .retval = TEST_DATA_LEN, | ||
7688 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 7710 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
7689 | }, | 7711 | }, |
7690 | { | 7712 | { |
@@ -8705,6 +8727,7 @@ static struct bpf_test tests[] = { | |||
8705 | .errstr_unpriv = "function calls to other bpf functions are allowed for root only", | 8727 | .errstr_unpriv = "function calls to other bpf functions are allowed for root only", |
8706 | .result_unpriv = REJECT, | 8728 | .result_unpriv = REJECT, |
8707 | .result = ACCEPT, | 8729 | .result = ACCEPT, |
8730 | .retval = 1, | ||
8708 | }, | 8731 | }, |
8709 | { | 8732 | { |
8710 | "calls: overlapping caller/callee", | 8733 | "calls: overlapping caller/callee", |
@@ -8900,6 +8923,7 @@ static struct bpf_test tests[] = { | |||
8900 | }, | 8923 | }, |
8901 | .prog_type = BPF_PROG_TYPE_SCHED_ACT, | 8924 | .prog_type = BPF_PROG_TYPE_SCHED_ACT, |
8902 | .result = ACCEPT, | 8925 | .result = ACCEPT, |
8926 | .retval = TEST_DATA_LEN, | ||
8903 | }, | 8927 | }, |
8904 | { | 8928 | { |
8905 | "calls: callee using args1", | 8929 | "calls: callee using args1", |
@@ -8912,6 +8936,7 @@ static struct bpf_test tests[] = { | |||
8912 | .errstr_unpriv = "allowed for root only", | 8936 | .errstr_unpriv = "allowed for root only", |
8913 | .result_unpriv = REJECT, | 8937 | .result_unpriv = REJECT, |
8914 | .result = ACCEPT, | 8938 | .result = ACCEPT, |
8939 | .retval = POINTER_VALUE, | ||
8915 | }, | 8940 | }, |
8916 | { | 8941 | { |
8917 | "calls: callee using wrong args2", | 8942 | "calls: callee using wrong args2", |
@@ -8942,6 +8967,7 @@ static struct bpf_test tests[] = { | |||
8942 | .errstr_unpriv = "allowed for root only", | 8967 | .errstr_unpriv = "allowed for root only", |
8943 | .result_unpriv = REJECT, | 8968 | .result_unpriv = REJECT, |
8944 | .result = ACCEPT, | 8969 | .result = ACCEPT, |
8970 | .retval = TEST_DATA_LEN + TEST_DATA_LEN - ETH_HLEN - ETH_HLEN, | ||
8945 | }, | 8971 | }, |
8946 | { | 8972 | { |
8947 | "calls: callee changing pkt pointers", | 8973 | "calls: callee changing pkt pointers", |
@@ -8990,6 +9016,7 @@ static struct bpf_test tests[] = { | |||
8990 | }, | 9016 | }, |
8991 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 9017 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
8992 | .result = ACCEPT, | 9018 | .result = ACCEPT, |
9019 | .retval = TEST_DATA_LEN + TEST_DATA_LEN, | ||
8993 | }, | 9020 | }, |
8994 | { | 9021 | { |
8995 | "calls: calls with stack arith", | 9022 | "calls: calls with stack arith", |
@@ -9008,6 +9035,7 @@ static struct bpf_test tests[] = { | |||
9008 | }, | 9035 | }, |
9009 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 9036 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
9010 | .result = ACCEPT, | 9037 | .result = ACCEPT, |
9038 | .retval = 42, | ||
9011 | }, | 9039 | }, |
9012 | { | 9040 | { |
9013 | "calls: calls with misaligned stack access", | 9041 | "calls: calls with misaligned stack access", |
@@ -9041,6 +9069,7 @@ static struct bpf_test tests[] = { | |||
9041 | }, | 9069 | }, |
9042 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 9070 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
9043 | .result = ACCEPT, | 9071 | .result = ACCEPT, |
9072 | .retval = 43, | ||
9044 | }, | 9073 | }, |
9045 | { | 9074 | { |
9046 | "calls: calls control flow, jump test 2", | 9075 | "calls: calls control flow, jump test 2", |
@@ -9533,6 +9562,7 @@ static struct bpf_test tests[] = { | |||
9533 | }, | 9562 | }, |
9534 | .prog_type = BPF_PROG_TYPE_XDP, | 9563 | .prog_type = BPF_PROG_TYPE_XDP, |
9535 | .result = ACCEPT, | 9564 | .result = ACCEPT, |
9565 | .retval = 42, | ||
9536 | }, | 9566 | }, |
9537 | { | 9567 | { |
9538 | "calls: write into callee stack frame", | 9568 | "calls: write into callee stack frame", |
@@ -10144,6 +10174,7 @@ static struct bpf_test tests[] = { | |||
10144 | }, | 10174 | }, |
10145 | .result = ACCEPT, | 10175 | .result = ACCEPT, |
10146 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 10176 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
10177 | .retval = POINTER_VALUE, | ||
10147 | }, | 10178 | }, |
10148 | { | 10179 | { |
10149 | "calls: pkt_ptr spill into caller stack 2", | 10180 | "calls: pkt_ptr spill into caller stack 2", |
@@ -10209,6 +10240,7 @@ static struct bpf_test tests[] = { | |||
10209 | }, | 10240 | }, |
10210 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 10241 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
10211 | .result = ACCEPT, | 10242 | .result = ACCEPT, |
10243 | .retval = 1, | ||
10212 | }, | 10244 | }, |
10213 | { | 10245 | { |
10214 | "calls: pkt_ptr spill into caller stack 4", | 10246 | "calls: pkt_ptr spill into caller stack 4", |
@@ -10242,6 +10274,7 @@ static struct bpf_test tests[] = { | |||
10242 | }, | 10274 | }, |
10243 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 10275 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
10244 | .result = ACCEPT, | 10276 | .result = ACCEPT, |
10277 | .retval = 1, | ||
10245 | }, | 10278 | }, |
10246 | { | 10279 | { |
10247 | "calls: pkt_ptr spill into caller stack 5", | 10280 | "calls: pkt_ptr spill into caller stack 5", |
@@ -10650,10 +10683,12 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
10650 | int fd_prog, expected_ret, reject_from_alignment; | 10683 | int fd_prog, expected_ret, reject_from_alignment; |
10651 | struct bpf_insn *prog = test->insns; | 10684 | struct bpf_insn *prog = test->insns; |
10652 | int prog_len = probe_filter_length(prog); | 10685 | int prog_len = probe_filter_length(prog); |
10686 | char data_in[TEST_DATA_LEN] = {}; | ||
10653 | int prog_type = test->prog_type; | 10687 | int prog_type = test->prog_type; |
10654 | int map_fds[MAX_NR_MAPS]; | 10688 | int map_fds[MAX_NR_MAPS]; |
10655 | const char *expected_err; | 10689 | const char *expected_err; |
10656 | int i; | 10690 | uint32_t retval; |
10691 | int i, err; | ||
10657 | 10692 | ||
10658 | for (i = 0; i < MAX_NR_MAPS; i++) | 10693 | for (i = 0; i < MAX_NR_MAPS; i++) |
10659 | map_fds[i] = -1; | 10694 | map_fds[i] = -1; |
@@ -10696,6 +10731,19 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
10696 | } | 10731 | } |
10697 | } | 10732 | } |
10698 | 10733 | ||
10734 | if (fd_prog >= 0) { | ||
10735 | err = bpf_prog_test_run(fd_prog, 1, data_in, sizeof(data_in), | ||
10736 | NULL, NULL, &retval, NULL); | ||
10737 | if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { | ||
10738 | printf("Unexpected bpf_prog_test_run error\n"); | ||
10739 | goto fail_log; | ||
10740 | } | ||
10741 | if (!err && retval != test->retval && | ||
10742 | test->retval != POINTER_VALUE) { | ||
10743 | printf("FAIL retval %d != %d\n", retval, test->retval); | ||
10744 | goto fail_log; | ||
10745 | } | ||
10746 | } | ||
10699 | (*passes)++; | 10747 | (*passes)++; |
10700 | printf("OK%s\n", reject_from_alignment ? | 10748 | printf("OK%s\n", reject_from_alignment ? |
10701 | " (NOTE: reject due to unknown alignment)" : ""); | 10749 | " (NOTE: reject due to unknown alignment)" : ""); |