Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Convert test_global_funcs test to test_loader framework

Convert 17 test_global_funcs subtests into test_loader framework for
easier maintenance and more declarative way to define expected
failures/successes.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/bpf/20230216045954.3002473-3-andrii@kernel.org

authored by

Andrii Nakryiko and committed by
Daniel Borkmann
95ebb376 d384dce2

+174 -123
+34 -97
tools/testing/selftests/bpf/prog_tests/test_global_funcs.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Copyright (c) 2020 Facebook */ 3 3 #include <test_progs.h> 4 - 5 - const char *err_str; 6 - bool found; 7 - 8 - static int libbpf_debug_print(enum libbpf_print_level level, 9 - const char *format, va_list args) 10 - { 11 - char *log_buf; 12 - 13 - if (level != LIBBPF_WARN || 14 - strcmp(format, "libbpf: \n%s\n")) { 15 - vprintf(format, args); 16 - return 0; 17 - } 18 - 19 - log_buf = va_arg(args, char *); 20 - if (!log_buf) 21 - goto out; 22 - if (err_str && strstr(log_buf, err_str) == 0) 23 - found = true; 24 - out: 25 - printf(format, log_buf); 26 - return 0; 27 - } 28 - 29 - extern int extra_prog_load_log_flags; 30 - 31 - static int check_load(const char *file) 32 - { 33 - struct bpf_object *obj = NULL; 34 - struct bpf_program *prog; 35 - int err; 36 - 37 - found = false; 38 - 39 - obj = bpf_object__open_file(file, NULL); 40 - err = libbpf_get_error(obj); 41 - if (err) 42 - return err; 43 - 44 - prog = bpf_object__next_program(obj, NULL); 45 - if (!prog) { 46 - err = -ENOENT; 47 - goto err_out; 48 - } 49 - 50 - bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32); 51 - bpf_program__set_log_level(prog, extra_prog_load_log_flags); 52 - 53 - err = bpf_object__load(obj); 54 - 55 - err_out: 56 - bpf_object__close(obj); 57 - return err; 58 - } 59 - 60 - struct test_def { 61 - const char *file; 62 - const char *err_str; 63 - }; 4 + #include "test_global_func1.skel.h" 5 + #include "test_global_func2.skel.h" 6 + #include "test_global_func3.skel.h" 7 + #include "test_global_func4.skel.h" 8 + #include "test_global_func5.skel.h" 9 + #include "test_global_func6.skel.h" 10 + #include "test_global_func7.skel.h" 11 + #include "test_global_func8.skel.h" 12 + #include "test_global_func9.skel.h" 13 + #include "test_global_func10.skel.h" 14 + #include "test_global_func11.skel.h" 15 + #include "test_global_func12.skel.h" 16 + #include "test_global_func13.skel.h" 17 + #include "test_global_func14.skel.h" 18 + #include "test_global_func15.skel.h" 19 + #include "test_global_func16.skel.h" 20 + #include "test_global_func17.skel.h" 64 21 65 22 void test_test_global_funcs(void) 66 23 { 67 - struct test_def tests[] = { 68 - { "test_global_func1.bpf.o", "combined stack size of 4 calls is 544" }, 69 - { "test_global_func2.bpf.o" }, 70 - { "test_global_func3.bpf.o", "the call stack of 8 frames" }, 71 - { "test_global_func4.bpf.o" }, 72 - { "test_global_func5.bpf.o", "expected pointer to ctx, but got PTR" }, 73 - { "test_global_func6.bpf.o", "modified ctx ptr R2" }, 74 - { "test_global_func7.bpf.o", "foo() doesn't return scalar" }, 75 - { "test_global_func8.bpf.o" }, 76 - { "test_global_func9.bpf.o" }, 77 - { "test_global_func10.bpf.o", "invalid indirect read from stack" }, 78 - { "test_global_func11.bpf.o", "Caller passes invalid args into func#1" }, 79 - { "test_global_func12.bpf.o", "invalid mem access 'mem_or_null'" }, 80 - { "test_global_func13.bpf.o", "Caller passes invalid args into func#1" }, 81 - { "test_global_func14.bpf.o", "reference type('FWD S') size cannot be determined" }, 82 - { "test_global_func15.bpf.o", "At program exit the register R0 has value" }, 83 - { "test_global_func16.bpf.o", "invalid indirect read from stack" }, 84 - { "test_global_func17.bpf.o", "Caller passes invalid args into func#1" }, 85 - }; 86 - libbpf_print_fn_t old_print_fn = NULL; 87 - int err, i, duration = 0; 88 - 89 - old_print_fn = libbpf_set_print(libbpf_debug_print); 90 - 91 - for (i = 0; i < ARRAY_SIZE(tests); i++) { 92 - const struct test_def *test = &tests[i]; 93 - 94 - if (!test__start_subtest(test->file)) 95 - continue; 96 - 97 - err_str = test->err_str; 98 - err = check_load(test->file); 99 - CHECK_FAIL(!!err ^ !!err_str); 100 - if (err_str) 101 - CHECK(found, "", "expected string '%s'", err_str); 102 - } 103 - libbpf_set_print(old_print_fn); 24 + RUN_TESTS(test_global_func1); 25 + RUN_TESTS(test_global_func2); 26 + RUN_TESTS(test_global_func3); 27 + RUN_TESTS(test_global_func4); 28 + RUN_TESTS(test_global_func5); 29 + RUN_TESTS(test_global_func6); 30 + RUN_TESTS(test_global_func7); 31 + RUN_TESTS(test_global_func8); 32 + RUN_TESTS(test_global_func9); 33 + RUN_TESTS(test_global_func10); 34 + RUN_TESTS(test_global_func11); 35 + RUN_TESTS(test_global_func12); 36 + RUN_TESTS(test_global_func13); 37 + RUN_TESTS(test_global_func14); 38 + RUN_TESTS(test_global_func15); 39 + RUN_TESTS(test_global_func16); 40 + RUN_TESTS(test_global_func17); 104 41 }
+3 -3
tools/testing/selftests/bpf/progs/test_global_func1.c
··· 3 3 #include <stddef.h> 4 4 #include <linux/bpf.h> 5 5 #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 6 7 7 - #ifndef MAX_STACK 8 8 #define MAX_STACK (512 - 3 * 32 + 8) 9 - #endif 10 9 11 10 static __attribute__ ((noinline)) 12 11 int f0(int var, struct __sk_buff *skb) ··· 38 39 } 39 40 40 41 SEC("tc") 41 - int test_cls(struct __sk_buff *skb) 42 + __failure __msg("combined stack size of 4 calls is 544") 43 + int global_func1(struct __sk_buff *skb) 42 44 { 43 45 return f0(1, skb) + f1(skb) + f2(2, skb) + f3(3, skb, 4); 44 46 }
+3 -1
tools/testing/selftests/bpf/progs/test_global_func10.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 struct Small { 7 8 int x; ··· 22 21 } 23 22 24 23 SEC("cgroup_skb/ingress") 25 - int test_cls(struct __sk_buff *skb) 24 + __failure __msg("invalid indirect read from stack") 25 + int global_func10(struct __sk_buff *skb) 26 26 { 27 27 const struct Small small = {.x = skb->len }; 28 28
+3 -1
tools/testing/selftests/bpf/progs/test_global_func11.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 struct S { 7 8 int x; ··· 14 13 } 15 14 16 15 SEC("cgroup_skb/ingress") 17 - int test_cls(struct __sk_buff *skb) 16 + __failure __msg("Caller passes invalid args into func#1") 17 + int global_func11(struct __sk_buff *skb) 18 18 { 19 19 return foo((const void *)skb); 20 20 }
+3 -1
tools/testing/selftests/bpf/progs/test_global_func12.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 struct S { 7 8 int x; ··· 14 13 } 15 14 16 15 SEC("cgroup_skb/ingress") 17 - int test_cls(struct __sk_buff *skb) 16 + __failure __msg("invalid mem access 'mem_or_null'") 17 + int global_func12(struct __sk_buff *skb) 18 18 { 19 19 const struct S s = {.x = skb->len }; 20 20
+3 -1
tools/testing/selftests/bpf/progs/test_global_func13.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 struct S { 7 8 int x; ··· 17 16 } 18 17 19 18 SEC("cgroup_skb/ingress") 20 - int test_cls(struct __sk_buff *skb) 19 + __failure __msg("Caller passes invalid args into func#1") 20 + int global_func13(struct __sk_buff *skb) 21 21 { 22 22 const struct S *s = (const struct S *)(0xbedabeda); 23 23
+3 -1
tools/testing/selftests/bpf/progs/test_global_func14.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 struct S; 7 8 ··· 15 14 } 16 15 17 16 SEC("cgroup_skb/ingress") 18 - int test_cls(struct __sk_buff *skb) 17 + __failure __msg("reference type('FWD S') size cannot be determined") 18 + int global_func14(struct __sk_buff *skb) 19 19 { 20 20 21 21 return foo(NULL);
+3 -1
tools/testing/selftests/bpf/progs/test_global_func15.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 __noinline int foo(unsigned int *v) 7 8 { ··· 13 12 } 14 13 15 14 SEC("cgroup_skb/ingress") 16 - int test_cls(struct __sk_buff *skb) 15 + __failure __msg("At program exit the register R0 has value") 16 + int global_func15(struct __sk_buff *skb) 17 17 { 18 18 unsigned int v = 1; 19 19
+3 -1
tools/testing/selftests/bpf/progs/test_global_func16.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 __noinline int foo(int (*arr)[10]) 7 8 { ··· 13 12 } 14 13 15 14 SEC("cgroup_skb/ingress") 16 - int test_cls(struct __sk_buff *skb) 15 + __failure __msg("invalid indirect read from stack") 16 + int global_func16(struct __sk_buff *skb) 17 17 { 18 18 int array[10]; 19 19
+3 -1
tools/testing/selftests/bpf/progs/test_global_func17.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 #include <vmlinux.h> 3 3 #include <bpf/bpf_helpers.h> 4 + #include "bpf_misc.h" 4 5 5 6 __noinline int foo(int *p) 6 7 { ··· 11 10 const volatile int i; 12 11 13 12 SEC("tc") 14 - int test_cls(struct __sk_buff *skb) 13 + __failure __msg("Caller passes invalid args into func#1") 14 + int global_func17(struct __sk_buff *skb) 15 15 { 16 16 return foo((int *)&i); 17 17 }
+42 -1
tools/testing/selftests/bpf/progs/test_global_func2.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* Copyright (c) 2020 Facebook */ 3 + #include <stddef.h> 4 + #include <linux/bpf.h> 5 + #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 7 + 3 8 #define MAX_STACK (512 - 3 * 32) 4 - #include "test_global_func1.c" 9 + 10 + static __attribute__ ((noinline)) 11 + int f0(int var, struct __sk_buff *skb) 12 + { 13 + return skb->len; 14 + } 15 + 16 + __attribute__ ((noinline)) 17 + int f1(struct __sk_buff *skb) 18 + { 19 + volatile char buf[MAX_STACK] = {}; 20 + 21 + return f0(0, skb) + skb->len; 22 + } 23 + 24 + int f3(int, struct __sk_buff *skb, int); 25 + 26 + __attribute__ ((noinline)) 27 + int f2(int val, struct __sk_buff *skb) 28 + { 29 + return f1(skb) + f3(val, skb, 1); 30 + } 31 + 32 + __attribute__ ((noinline)) 33 + int f3(int val, struct __sk_buff *skb, int var) 34 + { 35 + volatile char buf[MAX_STACK] = {}; 36 + 37 + return skb->ifindex * val * var; 38 + } 39 + 40 + SEC("tc") 41 + __success 42 + int global_func2(struct __sk_buff *skb) 43 + { 44 + return f0(1, skb) + f1(skb) + f2(2, skb) + f3(3, skb, 4); 45 + }
+3 -7
tools/testing/selftests/bpf/progs/test_global_func3.c
··· 3 3 #include <stddef.h> 4 4 #include <linux/bpf.h> 5 5 #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 6 7 7 8 __attribute__ ((noinline)) 8 9 int f1(struct __sk_buff *skb) ··· 47 46 return f6(skb); 48 47 } 49 48 50 - #ifndef NO_FN8 51 49 __attribute__ ((noinline)) 52 50 int f8(struct __sk_buff *skb) 53 51 { 54 52 return f7(skb); 55 53 } 56 - #endif 57 54 58 55 SEC("tc") 59 - int test_cls(struct __sk_buff *skb) 56 + __failure __msg("the call stack of 8 frames") 57 + int global_func3(struct __sk_buff *skb) 60 58 { 61 - #ifndef NO_FN8 62 59 return f8(skb); 63 - #else 64 - return f7(skb); 65 - #endif 66 60 }
+53 -2
tools/testing/selftests/bpf/progs/test_global_func4.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* Copyright (c) 2020 Facebook */ 3 - #define NO_FN8 4 - #include "test_global_func3.c" 3 + #include <stddef.h> 4 + #include <linux/bpf.h> 5 + #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 7 + 8 + __attribute__ ((noinline)) 9 + int f1(struct __sk_buff *skb) 10 + { 11 + return skb->len; 12 + } 13 + 14 + __attribute__ ((noinline)) 15 + int f2(int val, struct __sk_buff *skb) 16 + { 17 + return f1(skb) + val; 18 + } 19 + 20 + __attribute__ ((noinline)) 21 + int f3(int val, struct __sk_buff *skb, int var) 22 + { 23 + return f2(var, skb) + val; 24 + } 25 + 26 + __attribute__ ((noinline)) 27 + int f4(struct __sk_buff *skb) 28 + { 29 + return f3(1, skb, 2); 30 + } 31 + 32 + __attribute__ ((noinline)) 33 + int f5(struct __sk_buff *skb) 34 + { 35 + return f4(skb); 36 + } 37 + 38 + __attribute__ ((noinline)) 39 + int f6(struct __sk_buff *skb) 40 + { 41 + return f5(skb); 42 + } 43 + 44 + __attribute__ ((noinline)) 45 + int f7(struct __sk_buff *skb) 46 + { 47 + return f6(skb); 48 + } 49 + 50 + SEC("tc") 51 + __success 52 + int global_func4(struct __sk_buff *skb) 53 + { 54 + return f7(skb); 55 + }
+3 -1
tools/testing/selftests/bpf/progs/test_global_func5.c
··· 3 3 #include <stddef.h> 4 4 #include <linux/bpf.h> 5 5 #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 6 7 7 8 __attribute__ ((noinline)) 8 9 int f1(struct __sk_buff *skb) ··· 26 25 } 27 26 28 27 SEC("tc") 29 - int test_cls(struct __sk_buff *skb) 28 + __failure __msg("expected pointer to ctx, but got PTR") 29 + int global_func5(struct __sk_buff *skb) 30 30 { 31 31 return f1(skb) + f2(2, skb) + f3(3, skb); 32 32 }
+3 -1
tools/testing/selftests/bpf/progs/test_global_func6.c
··· 3 3 #include <stddef.h> 4 4 #include <linux/bpf.h> 5 5 #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 6 7 7 8 __attribute__ ((noinline)) 8 9 int f1(struct __sk_buff *skb) ··· 26 25 } 27 26 28 27 SEC("tc") 29 - int test_cls(struct __sk_buff *skb) 28 + __failure __msg("modified ctx ptr R2") 29 + int global_func6(struct __sk_buff *skb) 30 30 { 31 31 return f1(skb) + f2(2, skb) + f3(3, skb); 32 32 }
+3 -1
tools/testing/selftests/bpf/progs/test_global_func7.c
··· 3 3 #include <stddef.h> 4 4 #include <linux/bpf.h> 5 5 #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 6 7 7 8 __attribute__ ((noinline)) 8 9 void foo(struct __sk_buff *skb) ··· 12 11 } 13 12 14 13 SEC("tc") 15 - int test_cls(struct __sk_buff *skb) 14 + __failure __msg("foo() doesn't return scalar") 15 + int global_func7(struct __sk_buff *skb) 16 16 { 17 17 foo(skb); 18 18 return 0;
+3 -1
tools/testing/selftests/bpf/progs/test_global_func8.c
··· 3 3 #include <stddef.h> 4 4 #include <linux/bpf.h> 5 5 #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 6 7 7 8 __noinline int foo(struct __sk_buff *skb) 8 9 { ··· 11 10 } 12 11 13 12 SEC("cgroup_skb/ingress") 14 - int test_cls(struct __sk_buff *skb) 13 + __success 14 + int global_func8(struct __sk_buff *skb) 15 15 { 16 16 if (!foo(skb)) 17 17 return 0;
+3 -1
tools/testing/selftests/bpf/progs/test_global_func9.c
··· 2 2 #include <stddef.h> 3 3 #include <linux/bpf.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 6 7 struct S { 7 8 int x; ··· 75 74 } 76 75 77 76 SEC("cgroup_skb/ingress") 78 - int test_cls(struct __sk_buff *skb) 77 + __success 78 + int global_func9(struct __sk_buff *skb) 79 79 { 80 80 int result = 0; 81 81