mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-19 07:01:21 -04:00
selftests/bpf: Test ambiguous associated struct_ops
Add a test to make sure implicit struct_ops association does not break backward compatibility nor return incorrect struct_ops. struct_ops programs should still be allowed to be reused in different struct_ops map. The associated struct_ops map set implicitly however will be poisoned. Trying to read it through the helper bpf_prog_get_assoc_struct_ops() should result in a NULL pointer. While recursion of test_1() cannot happen due to the associated struct_ops being ambiguois, explicitly check for it to prevent stack overflow if the test regresses. Signed-off-by: Amery Hung <ameryhung@gmail.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20251203233748.668365-6-ameryhung@gmail.com
This commit is contained in:
committed by
Andrii Nakryiko
parent
33a165f9c2
commit
04fd12df4e
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <test_progs.h>
|
||||
#include "struct_ops_assoc.skel.h"
|
||||
#include "struct_ops_assoc_reuse.skel.h"
|
||||
|
||||
static void test_st_ops_assoc(void)
|
||||
{
|
||||
@@ -65,8 +66,45 @@ static void test_st_ops_assoc(void)
|
||||
struct_ops_assoc__destroy(skel);
|
||||
}
|
||||
|
||||
static void test_st_ops_assoc_reuse(void)
|
||||
{
|
||||
struct struct_ops_assoc_reuse *skel = NULL;
|
||||
int err;
|
||||
|
||||
skel = struct_ops_assoc_reuse__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "struct_ops_assoc_reuse__open"))
|
||||
goto out;
|
||||
|
||||
err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog_a,
|
||||
skel->maps.st_ops_map_a, NULL);
|
||||
ASSERT_OK(err, "bpf_program__assoc_struct_ops(syscall_prog_a, st_ops_map_a)");
|
||||
|
||||
err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog_b,
|
||||
skel->maps.st_ops_map_b, NULL);
|
||||
ASSERT_OK(err, "bpf_program__assoc_struct_ops(syscall_prog_b, st_ops_map_b)");
|
||||
|
||||
err = struct_ops_assoc_reuse__attach(skel);
|
||||
if (!ASSERT_OK(err, "struct_ops_assoc__attach"))
|
||||
goto out;
|
||||
|
||||
/* run syscall_prog that calls .test_1 and checks return */
|
||||
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog_a), NULL);
|
||||
ASSERT_OK(err, "bpf_prog_test_run_opts");
|
||||
|
||||
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog_b), NULL);
|
||||
ASSERT_OK(err, "bpf_prog_test_run_opts");
|
||||
|
||||
ASSERT_EQ(skel->bss->test_err_a, 0, "skel->bss->test_err_a");
|
||||
ASSERT_EQ(skel->bss->test_err_b, 0, "skel->bss->test_err_b");
|
||||
|
||||
out:
|
||||
struct_ops_assoc_reuse__destroy(skel);
|
||||
}
|
||||
|
||||
void test_struct_ops_assoc(void)
|
||||
{
|
||||
if (test__start_subtest("st_ops_assoc"))
|
||||
test_st_ops_assoc();
|
||||
if (test__start_subtest("st_ops_assoc_reuse"))
|
||||
test_st_ops_assoc_reuse();
|
||||
}
|
||||
|
||||
75
tools/testing/selftests/bpf/progs/struct_ops_assoc_reuse.c
Normal file
75
tools/testing/selftests/bpf/progs/struct_ops_assoc_reuse.c
Normal file
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <vmlinux.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include "bpf_misc.h"
|
||||
#include "../test_kmods/bpf_testmod.h"
|
||||
#include "../test_kmods/bpf_testmod_kfunc.h"
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
#define MAP_A_MAGIC 1234
|
||||
int test_err_a;
|
||||
int recur;
|
||||
|
||||
/*
|
||||
* test_1_a is reused. The kfunc should not be able to get the associated
|
||||
* struct_ops and call test_1 recursively as it is ambiguous.
|
||||
*/
|
||||
SEC("struct_ops")
|
||||
int BPF_PROG(test_1_a, struct st_ops_args *args)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!recur) {
|
||||
recur++;
|
||||
ret = bpf_kfunc_multi_st_ops_test_1_impl(args, NULL);
|
||||
if (ret != -1)
|
||||
test_err_a++;
|
||||
recur--;
|
||||
}
|
||||
|
||||
return MAP_A_MAGIC;
|
||||
}
|
||||
|
||||
/* Programs associated with st_ops_map_a */
|
||||
|
||||
SEC("syscall")
|
||||
int syscall_prog_a(void *ctx)
|
||||
{
|
||||
struct st_ops_args args = {};
|
||||
int ret;
|
||||
|
||||
ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
|
||||
if (ret != MAP_A_MAGIC)
|
||||
test_err_a++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC(".struct_ops.link")
|
||||
struct bpf_testmod_multi_st_ops st_ops_map_a = {
|
||||
.test_1 = (void *)test_1_a,
|
||||
};
|
||||
|
||||
/* Programs associated with st_ops_map_b */
|
||||
|
||||
int test_err_b;
|
||||
|
||||
SEC("syscall")
|
||||
int syscall_prog_b(void *ctx)
|
||||
{
|
||||
struct st_ops_args args = {};
|
||||
int ret;
|
||||
|
||||
ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
|
||||
if (ret != MAP_A_MAGIC)
|
||||
test_err_b++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC(".struct_ops.link")
|
||||
struct bpf_testmod_multi_st_ops st_ops_map_b = {
|
||||
.test_1 = (void *)test_1_a,
|
||||
};
|
||||
Reference in New Issue
Block a user