selftests/bpf: Ensure libbpf skip all-zeros fields of struct_ops maps.
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
This commit is contained in:
parent
c911fc61a7
commit
26a7cf2bbe
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user