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>
This commit is contained in:
Daniel Borkmann 2018-11-01 00:05:55 +01:00 committed by Alexei Starovoitov
parent 2683f4128c
commit 832c6f2c29

View File

@ -76,7 +76,7 @@ struct bpf_test {
int fixup_percpu_cgroup_storage[MAX_FIXUPS]; int fixup_percpu_cgroup_storage[MAX_FIXUPS];
const char *errstr; const char *errstr;
const char *errstr_unpriv; const char *errstr_unpriv;
uint32_t retval; uint32_t retval, retval_unpriv;
enum { enum {
UNDEF, UNDEF,
ACCEPT, ACCEPT,
@ -3084,6 +3084,8 @@ static struct bpf_test tests[] = {
.fixup_prog1 = { 2 }, .fixup_prog1 = { 2 },
.result = ACCEPT, .result = ACCEPT,
.retval = 42, .retval = 42,
/* Verifier rewrite for unpriv skips tail call here. */
.retval_unpriv = 2,
}, },
{ {
"stack pointer arithmetic", "stack pointer arithmetic",
@ -14149,6 +14151,33 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_map_type prog_type,
} }
} }
static int set_admin(bool admin)
{
cap_t caps;
const cap_value_t cap_val = CAP_SYS_ADMIN;
int ret = -1;
caps = cap_get_proc();
if (!caps) {
perror("cap_get_proc");
return -1;
}
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val,
admin ? CAP_SET : CAP_CLEAR)) {
perror("cap_set_flag");
goto out;
}
if (cap_set_proc(caps)) {
perror("cap_set_proc");
goto out;
}
ret = 0;
out:
if (cap_free(caps))
perror("cap_free");
return ret;
}
static void do_test_single(struct bpf_test *test, bool unpriv, static void do_test_single(struct bpf_test *test, bool unpriv,
int *passes, int *errors) int *passes, int *errors)
{ {
@ -14157,6 +14186,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
struct bpf_insn *prog = test->insns; struct bpf_insn *prog = test->insns;
int map_fds[MAX_NR_MAPS]; int map_fds[MAX_NR_MAPS];
const char *expected_err; const char *expected_err;
uint32_t expected_val;
uint32_t retval; uint32_t retval;
int i, err; int i, err;
@ -14176,6 +14206,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
test->result_unpriv : test->result; test->result_unpriv : test->result;
expected_err = unpriv && test->errstr_unpriv ? expected_err = unpriv && test->errstr_unpriv ?
test->errstr_unpriv : test->errstr; test->errstr_unpriv : test->errstr;
expected_val = unpriv && test->retval_unpriv ?
test->retval_unpriv : test->retval;
reject_from_alignment = fd_prog < 0 && reject_from_alignment = fd_prog < 0 &&
(test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) && (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) &&
@ -14209,16 +14241,20 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
__u8 tmp[TEST_DATA_LEN << 2]; __u8 tmp[TEST_DATA_LEN << 2];
__u32 size_tmp = sizeof(tmp); __u32 size_tmp = sizeof(tmp);
if (unpriv)
set_admin(true);
err = bpf_prog_test_run(fd_prog, 1, test->data, err = bpf_prog_test_run(fd_prog, 1, test->data,
sizeof(test->data), tmp, &size_tmp, sizeof(test->data), tmp, &size_tmp,
&retval, NULL); &retval, NULL);
if (unpriv)
set_admin(false);
if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) {
printf("Unexpected bpf_prog_test_run error\n"); printf("Unexpected bpf_prog_test_run error\n");
goto fail_log; goto fail_log;
} }
if (!err && retval != test->retval && if (!err && retval != expected_val &&
test->retval != POINTER_VALUE) { expected_val != POINTER_VALUE) {
printf("FAIL retval %d != %d\n", retval, test->retval); printf("FAIL retval %d != %d\n", retval, expected_val);
goto fail_log; goto fail_log;
} }
} }
@ -14261,33 +14297,6 @@ static bool is_admin(void)
return (sysadmin == CAP_SET); return (sysadmin == CAP_SET);
} }
static int set_admin(bool admin)
{
cap_t caps;
const cap_value_t cap_val = CAP_SYS_ADMIN;
int ret = -1;
caps = cap_get_proc();
if (!caps) {
perror("cap_get_proc");
return -1;
}
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val,
admin ? CAP_SET : CAP_CLEAR)) {
perror("cap_set_flag");
goto out;
}
if (cap_set_proc(caps)) {
perror("cap_set_proc");
goto out;
}
ret = 0;
out:
if (cap_free(caps))
perror("cap_free");
return ret;
}
static void get_unpriv_disabled() static void get_unpriv_disabled()
{ {
char buf[2]; char buf[2];