]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
selftests/bpf: Ensure libbpf skip all-zeros fields of struct_ops maps.
authorKui-Feng Lee <thinker.li@gmail.com>
Wed, 13 Mar 2024 21:41:38 +0000 (14:41 -0700)
committerAndrii Nakryiko <andrii@kernel.org>
Thu, 14 Mar 2024 20:47:05 +0000 (13:47 -0700)
A new version of a type may have additional fields that do not exist in
older versions. Previously, libbpf would reject struct_ops maps with a new
version containing extra fields when running on a machine with an old
kernel. However, we have updated libbpf to ignore these fields if their
values are all zeros or null in order to provide backward compatibility.

Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20240313214139.685112-3-thinker.li@gmail.com
tools/testing/selftests/bpf/prog_tests/test_struct_ops_module.c
tools/testing/selftests/bpf/progs/struct_ops_module.c

index ee5372c7f2c7c92b6b278a156753fcbecc5a8059..098776d00ab4b493358b60300cfc89d61471d564 100644 (file)
@@ -93,9 +93,56 @@ cleanup:
        struct_ops_module__destroy(skel);
 }
 
+static void test_struct_ops_not_zeroed(void)
+{
+       struct struct_ops_module *skel;
+       int err;
+
+       /* zeroed is 0, and zeroed_op is null */
+       skel = struct_ops_module__open();
+       if (!ASSERT_OK_PTR(skel, "struct_ops_module_open"))
+               return;
+
+       err = struct_ops_module__load(skel);
+       ASSERT_OK(err, "struct_ops_module_load");
+
+       struct_ops_module__destroy(skel);
+
+       /* zeroed is not 0 */
+       skel = struct_ops_module__open();
+       if (!ASSERT_OK_PTR(skel, "struct_ops_module_open_not_zeroed"))
+               return;
+
+       /* libbpf should reject the testmod_zeroed since struct
+        * bpf_testmod_ops in the kernel has no "zeroed" field and the
+        * value of "zeroed" is non-zero.
+        */
+       skel->struct_ops.testmod_zeroed->zeroed = 0xdeadbeef;
+       err = struct_ops_module__load(skel);
+       ASSERT_ERR(err, "struct_ops_module_load_not_zeroed");
+
+       struct_ops_module__destroy(skel);
+
+       /* zeroed_op is not null */
+       skel = struct_ops_module__open();
+       if (!ASSERT_OK_PTR(skel, "struct_ops_module_open_not_zeroed_op"))
+               return;
+
+       /* libbpf should reject the testmod_zeroed since the value of its
+        * "zeroed_op" is not null.
+        */
+       skel->struct_ops.testmod_zeroed->zeroed_op = skel->progs.test_3;
+       err = struct_ops_module__load(skel);
+       ASSERT_ERR(err, "struct_ops_module_load_not_zeroed_op");
+
+       struct_ops_module__destroy(skel);
+}
+
 void serial_test_struct_ops_module(void)
 {
        if (test__start_subtest("test_struct_ops_load"))
                test_struct_ops_load();
+       if (test__start_subtest("test_struct_ops_not_zeroed"))
+               test_struct_ops_not_zeroed();
 }
 
index 026cabfa7f1f671ce988da8332607ae25ee9db85..86e1e50c5531ec37449fbea2d0ab1c2410fb0223 100644 (file)
@@ -23,7 +23,7 @@ void BPF_PROG(test_2, int a, int b)
        test_2_result = a + b;
 }
 
-SEC("struct_ops/test_3")
+SEC("?struct_ops/test_3")
 int BPF_PROG(test_3, int a, int b)
 {
        test_2_result = a + b + 3;
@@ -54,3 +54,17 @@ struct bpf_testmod_ops___v2 testmod_2 = {
        .test_1 = (void *)test_1,
        .test_2 = (void *)test_2_v2,
 };
+
+struct bpf_testmod_ops___zeroed {
+       int (*test_1)(void);
+       void (*test_2)(int a, int b);
+       int (*test_maybe_null)(int dummy, struct task_struct *task);
+       void (*zeroed_op)(int a, int b);
+       int zeroed;
+};
+
+SEC(".struct_ops.link")
+struct bpf_testmod_ops___zeroed testmod_zeroed = {
+       .test_1 = (void *)test_1,
+       .test_2 = (void *)test_2_v2,
+};