diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-10-31 19:05:55 -0400 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-10-31 19:53:17 -0400 |
commit | 832c6f2c29ec519b766923937f4f93fb1008b47d (patch) | |
tree | 580d9ce17012b6dce0d9da1b9a4993cf9e602605 /tools/testing | |
parent | 2683f4128c8730699296827d3209d2de80fa1d6c (diff) |
bpf: test make sure to run unpriv test cases in test_verifier
Right now unprivileged tests are never executed as a BPF test run,
only loaded. Allow for running them as well so that we can check
the outcome and probe for regressions.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/testing')
-rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 71 |
1 files changed, 40 insertions, 31 deletions
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 4c7445d4b3e6..6f61df62f690 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
@@ -76,7 +76,7 @@ struct bpf_test { | |||
76 | int fixup_percpu_cgroup_storage[MAX_FIXUPS]; | 76 | int fixup_percpu_cgroup_storage[MAX_FIXUPS]; |
77 | const char *errstr; | 77 | const char *errstr; |
78 | const char *errstr_unpriv; | 78 | const char *errstr_unpriv; |
79 | uint32_t retval; | 79 | uint32_t retval, retval_unpriv; |
80 | enum { | 80 | enum { |
81 | UNDEF, | 81 | UNDEF, |
82 | ACCEPT, | 82 | ACCEPT, |
@@ -3084,6 +3084,8 @@ static struct bpf_test tests[] = { | |||
3084 | .fixup_prog1 = { 2 }, | 3084 | .fixup_prog1 = { 2 }, |
3085 | .result = ACCEPT, | 3085 | .result = ACCEPT, |
3086 | .retval = 42, | 3086 | .retval = 42, |
3087 | /* Verifier rewrite for unpriv skips tail call here. */ | ||
3088 | .retval_unpriv = 2, | ||
3087 | }, | 3089 | }, |
3088 | { | 3090 | { |
3089 | "stack pointer arithmetic", | 3091 | "stack pointer arithmetic", |
@@ -14149,6 +14151,33 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_map_type prog_type, | |||
14149 | } | 14151 | } |
14150 | } | 14152 | } |
14151 | 14153 | ||
14154 | static int set_admin(bool admin) | ||
14155 | { | ||
14156 | cap_t caps; | ||
14157 | const cap_value_t cap_val = CAP_SYS_ADMIN; | ||
14158 | int ret = -1; | ||
14159 | |||
14160 | caps = cap_get_proc(); | ||
14161 | if (!caps) { | ||
14162 | perror("cap_get_proc"); | ||
14163 | return -1; | ||
14164 | } | ||
14165 | if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val, | ||
14166 | admin ? CAP_SET : CAP_CLEAR)) { | ||
14167 | perror("cap_set_flag"); | ||
14168 | goto out; | ||
14169 | } | ||
14170 | if (cap_set_proc(caps)) { | ||
14171 | perror("cap_set_proc"); | ||
14172 | goto out; | ||
14173 | } | ||
14174 | ret = 0; | ||
14175 | out: | ||
14176 | if (cap_free(caps)) | ||
14177 | perror("cap_free"); | ||
14178 | return ret; | ||
14179 | } | ||
14180 | |||
14152 | static void do_test_single(struct bpf_test *test, bool unpriv, | 14181 | static void do_test_single(struct bpf_test *test, bool unpriv, |
14153 | int *passes, int *errors) | 14182 | int *passes, int *errors) |
14154 | { | 14183 | { |
@@ -14157,6 +14186,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
14157 | struct bpf_insn *prog = test->insns; | 14186 | struct bpf_insn *prog = test->insns; |
14158 | int map_fds[MAX_NR_MAPS]; | 14187 | int map_fds[MAX_NR_MAPS]; |
14159 | const char *expected_err; | 14188 | const char *expected_err; |
14189 | uint32_t expected_val; | ||
14160 | uint32_t retval; | 14190 | uint32_t retval; |
14161 | int i, err; | 14191 | int i, err; |
14162 | 14192 | ||
@@ -14176,6 +14206,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
14176 | test->result_unpriv : test->result; | 14206 | test->result_unpriv : test->result; |
14177 | expected_err = unpriv && test->errstr_unpriv ? | 14207 | expected_err = unpriv && test->errstr_unpriv ? |
14178 | test->errstr_unpriv : test->errstr; | 14208 | test->errstr_unpriv : test->errstr; |
14209 | expected_val = unpriv && test->retval_unpriv ? | ||
14210 | test->retval_unpriv : test->retval; | ||
14179 | 14211 | ||
14180 | reject_from_alignment = fd_prog < 0 && | 14212 | reject_from_alignment = fd_prog < 0 && |
14181 | (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) && | 14213 | (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) && |
@@ -14209,16 +14241,20 @@ static void do_test_single(struct bpf_test *test, bool unpriv, | |||
14209 | __u8 tmp[TEST_DATA_LEN << 2]; | 14241 | __u8 tmp[TEST_DATA_LEN << 2]; |
14210 | __u32 size_tmp = sizeof(tmp); | 14242 | __u32 size_tmp = sizeof(tmp); |
14211 | 14243 | ||
14244 | if (unpriv) | ||
14245 | set_admin(true); | ||
14212 | err = bpf_prog_test_run(fd_prog, 1, test->data, | 14246 | err = bpf_prog_test_run(fd_prog, 1, test->data, |
14213 | sizeof(test->data), tmp, &size_tmp, | 14247 | sizeof(test->data), tmp, &size_tmp, |
14214 | &retval, NULL); | 14248 | &retval, NULL); |
14249 | if (unpriv) | ||
14250 | set_admin(false); | ||
14215 | if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { | 14251 | if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { |
14216 | printf("Unexpected bpf_prog_test_run error\n"); | 14252 | printf("Unexpected bpf_prog_test_run error\n"); |
14217 | goto fail_log; | 14253 | goto fail_log; |
14218 | } | 14254 | } |
14219 | if (!err && retval != test->retval && | 14255 | if (!err && retval != expected_val && |
14220 | test->retval != POINTER_VALUE) { | 14256 | expected_val != POINTER_VALUE) { |
14221 | printf("FAIL retval %d != %d\n", retval, test->retval); | 14257 | printf("FAIL retval %d != %d\n", retval, expected_val); |
14222 | goto fail_log; | 14258 | goto fail_log; |
14223 | } | 14259 | } |
14224 | } | 14260 | } |
@@ -14261,33 +14297,6 @@ static bool is_admin(void) | |||
14261 | return (sysadmin == CAP_SET); | 14297 | return (sysadmin == CAP_SET); |
14262 | } | 14298 | } |
14263 | 14299 | ||
14264 | static int set_admin(bool admin) | ||
14265 | { | ||
14266 | cap_t caps; | ||
14267 | const cap_value_t cap_val = CAP_SYS_ADMIN; | ||
14268 | int ret = -1; | ||
14269 | |||
14270 | caps = cap_get_proc(); | ||
14271 | if (!caps) { | ||
14272 | perror("cap_get_proc"); | ||
14273 | return -1; | ||
14274 | } | ||
14275 | if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val, | ||
14276 | admin ? CAP_SET : CAP_CLEAR)) { | ||
14277 | perror("cap_set_flag"); | ||
14278 | goto out; | ||
14279 | } | ||
14280 | if (cap_set_proc(caps)) { | ||
14281 | perror("cap_set_proc"); | ||
14282 | goto out; | ||
14283 | } | ||
14284 | ret = 0; | ||
14285 | out: | ||
14286 | if (cap_free(caps)) | ||
14287 | perror("cap_free"); | ||
14288 | return ret; | ||
14289 | } | ||
14290 | |||
14291 | static void get_unpriv_disabled() | 14300 | static void get_unpriv_disabled() |
14292 | { | 14301 | { |
14293 | char buf[2]; | 14302 | char buf[2]; |