selftests/bpf: set BPF_F_TEST_SANITY_SCRIPT by default
authorAndrii Nakryiko <andrii@kernel.org>
Sun, 12 Nov 2023 01:06:07 +0000 (17:06 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 15 Nov 2023 20:03:42 +0000 (12:03 -0800)
Make sure to set BPF_F_TEST_SANITY_STRICT program flag by default across
most verifier tests (and a bunch of others that set custom prog flags).

There are currently two tests that do fail validation, if enforced
strictly: verifier_bounds/crossing_64_bit_signed_boundary_2 and
verifier_bounds/crossing_32_bit_signed_boundary_2. To accommodate them,
we teach test_loader a flag negation:

__flag(!<flagname>) will *clear* specified flag, allowing easy opt-out.

We apply __flag(!BPF_F_TEST_SANITY_STRICT) to these to tests.

Also sprinkle BPF_F_TEST_SANITY_STRICT everywhere where we already set
test-only BPF_F_TEST_RND_HI32 flag, for completeness.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20231112010609.848406-12-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
tools/testing/selftests/bpf/progs/verifier_bounds.c
tools/testing/selftests/bpf/test_loader.c
tools/testing/selftests/bpf/test_sock_addr.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/bpf/testing_helpers.c

index 731c343897d8fb90ed50c16ef992dd38831141b6..3f2d7083187359ae1279b1e3274d0146a40c1340 100644 (file)
@@ -35,7 +35,7 @@ static int check_load(const char *file, enum bpf_prog_type type)
        }
 
        bpf_program__set_type(prog, type);
-       bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32);
+       bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32 | BPF_F_TEST_SANITY_STRICT);
        bpf_program__set_log_level(prog, 4 | extra_prog_load_log_flags);
 
        err = bpf_object__load(obj);
index c5588a14fe2e36109520eb38384a1e03053049a3..0c1460936373102f45819827f1bac9bacf726a65 100644 (file)
@@ -965,6 +965,7 @@ l0_%=:      r0 = 0;                                         \
 SEC("xdp")
 __description("bound check with JMP_JSLT for crossing 64-bit signed boundary")
 __success __retval(0)
+__flag(!BPF_F_TEST_SANITY_STRICT) /* known sanity violation */
 __naked void crossing_64_bit_signed_boundary_2(void)
 {
        asm volatile ("                                 \
@@ -1046,6 +1047,7 @@ l0_%=:    r0 = 0;                                         \
 SEC("xdp")
 __description("bound check with JMP32_JSLT for crossing 32-bit signed boundary")
 __success __retval(0)
+__flag(!BPF_F_TEST_SANITY_STRICT) /* known sanity violation */
 __naked void crossing_32_bit_signed_boundary_2(void)
 {
        asm volatile ("                                 \
index 37ffa57f28a192c386dd0a73790ffbf29755c0f9..57e27b1a73a6fcfe7023a30e911677f690a04e2c 100644 (file)
@@ -153,6 +153,14 @@ static int parse_retval(const char *str, int *val, const char *name)
        return parse_int(str, val, name);
 }
 
+static void update_flags(int *flags, int flag, bool clear)
+{
+       if (clear)
+               *flags &= ~flag;
+       else
+               *flags |= flag;
+}
+
 /* Uses btf_decl_tag attributes to describe the expected test
  * behavior, see bpf_misc.h for detailed description of each attribute
  * and attribute combinations.
@@ -171,6 +179,7 @@ static int parse_test_spec(struct test_loader *tester,
        memset(spec, 0, sizeof(*spec));
 
        spec->prog_name = bpf_program__name(prog);
+       spec->prog_flags = BPF_F_TEST_SANITY_STRICT; /* by default be strict */
 
        btf = bpf_object__btf(obj);
        if (!btf) {
@@ -187,7 +196,8 @@ static int parse_test_spec(struct test_loader *tester,
        for (i = 1; i < btf__type_cnt(btf); i++) {
                const char *s, *val, *msg;
                const struct btf_type *t;
-               int tmp;
+               bool clear;
+               int flags;
 
                t = btf__type_by_id(btf, i);
                if (!btf_is_decl_tag(t))
@@ -253,23 +263,30 @@ static int parse_test_spec(struct test_loader *tester,
                                goto cleanup;
                } else if (str_has_pfx(s, TEST_TAG_PROG_FLAGS_PFX)) {
                        val = s + sizeof(TEST_TAG_PROG_FLAGS_PFX) - 1;
+
+                       clear = val[0] == '!';
+                       if (clear)
+                               val++;
+
                        if (strcmp(val, "BPF_F_STRICT_ALIGNMENT") == 0) {
-                               spec->prog_flags |= BPF_F_STRICT_ALIGNMENT;
+                               update_flags(&spec->prog_flags, BPF_F_STRICT_ALIGNMENT, clear);
                        } else if (strcmp(val, "BPF_F_ANY_ALIGNMENT") == 0) {
-                               spec->prog_flags |= BPF_F_ANY_ALIGNMENT;
+                               update_flags(&spec->prog_flags, BPF_F_ANY_ALIGNMENT, clear);
                        } else if (strcmp(val, "BPF_F_TEST_RND_HI32") == 0) {
-                               spec->prog_flags |= BPF_F_TEST_RND_HI32;
+                               update_flags(&spec->prog_flags, BPF_F_TEST_RND_HI32, clear);
                        } else if (strcmp(val, "BPF_F_TEST_STATE_FREQ") == 0) {
-                               spec->prog_flags |= BPF_F_TEST_STATE_FREQ;
+                               update_flags(&spec->prog_flags, BPF_F_TEST_STATE_FREQ, clear);
                        } else if (strcmp(val, "BPF_F_SLEEPABLE") == 0) {
-                               spec->prog_flags |= BPF_F_SLEEPABLE;
+                               update_flags(&spec->prog_flags, BPF_F_SLEEPABLE, clear);
                        } else if (strcmp(val, "BPF_F_XDP_HAS_FRAGS") == 0) {
-                               spec->prog_flags |= BPF_F_XDP_HAS_FRAGS;
+                               update_flags(&spec->prog_flags, BPF_F_XDP_HAS_FRAGS, clear);
+                       } else if (strcmp(val, "BPF_F_TEST_SANITY_STRICT") == 0) {
+                               update_flags(&spec->prog_flags, BPF_F_TEST_SANITY_STRICT, clear);
                        } else /* assume numeric value */ {
-                               err = parse_int(val, &tmp, "test prog flags");
+                               err = parse_int(val, &flags, "test prog flags");
                                if (err)
                                        goto cleanup;
-                               spec->prog_flags |= tmp;
+                               update_flags(&spec->prog_flags, flags, clear);
                        }
                }
        }
index 2c89674fc62c1581b95146ef1e9c9d4afa9a0262..878c077e0fa72993458a37f3af025094a932e28f 100644 (file)
@@ -680,6 +680,7 @@ static int load_path(const struct sock_addr_test *test, const char *path)
        bpf_program__set_type(prog, BPF_PROG_TYPE_CGROUP_SOCK_ADDR);
        bpf_program__set_expected_attach_type(prog, test->expected_attach_type);
        bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32);
+       bpf_program__set_flags(prog, BPF_F_TEST_SANITY_STRICT);
 
        err = bpf_object__load(obj);
        if (err) {
index 98107e0452d338aee8e2f722e939dab95b6e0e52..4992022f3137262392ae488e415c4e8a2c37dfad 100644 (file)
@@ -1588,7 +1588,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
        if (fixup_skips != skips)
                return;
 
-       pflags = BPF_F_TEST_RND_HI32;
+       pflags = BPF_F_TEST_RND_HI32 | BPF_F_TEST_SANITY_STRICT;
        if (test->flags & F_LOAD_WITH_STRICT_ALIGNMENT)
                pflags |= BPF_F_STRICT_ALIGNMENT;
        if (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS)
index 8d994884c7b440c78ed8982f18b5393cdbf2fb01..9786a94a666c59b9666b2a0241db5f27a88efa5a 100644 (file)
@@ -276,7 +276,7 @@ int bpf_prog_test_load(const char *file, enum bpf_prog_type type,
        if (type != BPF_PROG_TYPE_UNSPEC && bpf_program__type(prog) != type)
                bpf_program__set_type(prog, type);
 
-       flags = bpf_program__flags(prog) | BPF_F_TEST_RND_HI32;
+       flags = bpf_program__flags(prog) | BPF_F_TEST_RND_HI32 | BPF_F_TEST_SANITY_STRICT;
        bpf_program__set_flags(prog, flags);
 
        err = bpf_object__load(obj);
@@ -299,7 +299,7 @@ int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
 {
        LIBBPF_OPTS(bpf_prog_load_opts, opts,
                .kern_version = kern_version,
-               .prog_flags = BPF_F_TEST_RND_HI32,
+               .prog_flags = BPF_F_TEST_RND_HI32 | BPF_F_TEST_SANITY_STRICT,
                .log_level = extra_prog_load_log_flags,
                .log_buf = log_buf,
                .log_size = log_buf_sz,