Skip to content

Commit

Permalink
bpf: Always test unprivileged programs
Browse files Browse the repository at this point in the history
If selftests are run as root, then execute the unprivileged checks as
well. This switch from 243 to 368 tests.

The test numbers are suffixed with "/u" when executed as unprivileged or
with "/p" when executed as privileged.

The geteuid() check is replaced with a capability check.

Handling capabilities requires the libcap dependency.

Signed-off-by: Mickaël Salaün <mic@digikod.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Mickaël Salaün authored and David S. Miller committed Feb 10, 2017
1 parent 7f73f39 commit d02d898
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 6 deletions.
2 changes: 1 addition & 1 deletion tools/testing/selftests/bpf/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CFLAGS += -Wall -O2 -I../../../include/uapi
CFLAGS += -Wall -O2 -lcap -I../../../include/uapi

test_objs = test_verifier test_tag test_maps test_lru_map test_lpm_map

Expand Down
68 changes: 63 additions & 5 deletions tools/testing/selftests/bpf/test_verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <stdbool.h>
#include <sched.h>

#include <sys/capability.h>
#include <sys/resource.h>

#include <linux/unistd.h>
Expand Down Expand Up @@ -4574,6 +4575,55 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
goto close_fds;
}

static bool is_admin(void)
{
cap_t caps;
cap_flag_value_t sysadmin = CAP_CLEAR;
const cap_value_t cap_val = CAP_SYS_ADMIN;

if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) {
perror("cap_get_flag");
return false;
}
caps = cap_get_proc();
if (!caps) {
perror("cap_get_proc");
return false;
}
if (cap_get_flag(caps, cap_val, CAP_EFFECTIVE, &sysadmin))
perror("cap_get_flag");
if (cap_free(caps))
perror("cap_free");
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 int do_test(bool unpriv, unsigned int from, unsigned int to)
{
int i, passes = 0, errors = 0;
Expand All @@ -4584,11 +4634,19 @@ static int do_test(bool unpriv, unsigned int from, unsigned int to)
/* Program types that are not supported by non-root we
* skip right away.
*/
if (unpriv && test->prog_type)
continue;
if (!test->prog_type) {
if (!unpriv)
set_admin(false);
printf("#%d/u %s ", i, test->descr);
do_test_single(test, true, &passes, &errors);
if (!unpriv)
set_admin(true);
}

printf("#%d %s ", i, test->descr);
do_test_single(test, unpriv, &passes, &errors);
if (!unpriv) {
printf("#%d/p %s ", i, test->descr);
do_test_single(test, false, &passes, &errors);
}
}

printf("Summary: %d PASSED, %d FAILED\n", passes, errors);
Expand All @@ -4600,7 +4658,7 @@ int main(int argc, char **argv)
struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
struct rlimit rlim = { 1 << 20, 1 << 20 };
unsigned int from = 0, to = ARRAY_SIZE(tests);
bool unpriv = geteuid() != 0;
bool unpriv = !is_admin();

if (argc == 3) {
unsigned int l = atoi(argv[argc - 2]);
Expand Down

0 comments on commit d02d898

Please sign in to comment.