Skip to content

Commit c1b93c0

Browse files
eddyz87anakryiko
authored andcommitted
selftests/bpf: Bad_struct_ops test
When loading struct_ops programs kernel requires BTF id of the struct_ops type and member index for attachment point inside that type. This makes impossible to use same BPF program in several struct_ops maps that have different struct_ops type. Check if libbpf rejects such BPF objects files. Signed-off-by: Eduard Zingerman <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent c8617e8 commit c1b93c0

File tree

4 files changed

+88
-0
lines changed

4 files changed

+88
-0
lines changed

tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,29 @@ struct bpf_struct_ops bpf_bpf_testmod_ops = {
611611
.owner = THIS_MODULE,
612612
};
613613

614+
static int bpf_dummy_reg2(void *kdata)
615+
{
616+
struct bpf_testmod_ops2 *ops = kdata;
617+
618+
ops->test_1();
619+
return 0;
620+
}
621+
622+
static struct bpf_testmod_ops2 __bpf_testmod_ops2 = {
623+
.test_1 = bpf_testmod_test_1,
624+
};
625+
626+
struct bpf_struct_ops bpf_testmod_ops2 = {
627+
.verifier_ops = &bpf_testmod_verifier_ops,
628+
.init = bpf_testmod_ops_init,
629+
.init_member = bpf_testmod_ops_init_member,
630+
.reg = bpf_dummy_reg2,
631+
.unreg = bpf_dummy_unreg,
632+
.cfi_stubs = &__bpf_testmod_ops2,
633+
.name = "bpf_testmod_ops2",
634+
.owner = THIS_MODULE,
635+
};
636+
614637
extern int bpf_fentry_test1(int a);
615638

616639
static int bpf_testmod_init(void)
@@ -622,6 +645,7 @@ static int bpf_testmod_init(void)
622645
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_testmod_kfunc_set);
623646
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &bpf_testmod_kfunc_set);
624647
ret = ret ?: register_bpf_struct_ops(&bpf_bpf_testmod_ops, bpf_testmod_ops);
648+
ret = ret ?: register_bpf_struct_ops(&bpf_testmod_ops2, bpf_testmod_ops2);
625649
if (ret < 0)
626650
return ret;
627651
if (bpf_fentry_test1(0) < 0)

tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,8 @@ struct bpf_testmod_ops {
8989
int (*tramp_40)(int value);
9090
};
9191

92+
struct bpf_testmod_ops2 {
93+
int (*test_1)(void);
94+
};
95+
9296
#endif /* _BPF_TESTMOD_H */
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <test_progs.h>
4+
#include "bad_struct_ops.skel.h"
5+
6+
static void invalid_prog_reuse(void)
7+
{
8+
struct bad_struct_ops *skel;
9+
char *log = NULL;
10+
int err;
11+
12+
skel = bad_struct_ops__open();
13+
if (!ASSERT_OK_PTR(skel, "bad_struct_ops__open"))
14+
return;
15+
16+
if (start_libbpf_log_capture())
17+
goto cleanup;
18+
19+
err = bad_struct_ops__load(skel);
20+
log = stop_libbpf_log_capture();
21+
ASSERT_ERR(err, "bad_struct_ops__load should fail");
22+
ASSERT_HAS_SUBSTR(log,
23+
"struct_ops init_kern testmod_2 func ptr test_1: invalid reuse of prog test_1",
24+
"expected init_kern message");
25+
26+
cleanup:
27+
free(log);
28+
bad_struct_ops__destroy(skel);
29+
}
30+
31+
void test_bad_struct_ops(void)
32+
{
33+
if (test__start_subtest("invalid_prog_reuse"))
34+
invalid_prog_reuse();
35+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include "../bpf_testmod/bpf_testmod.h"
7+
8+
char _license[] SEC("license") = "GPL";
9+
10+
SEC("struct_ops/test_1")
11+
int BPF_PROG(test_1) { return 0; }
12+
13+
SEC("struct_ops/test_2")
14+
int BPF_PROG(test_2) { return 0; }
15+
16+
SEC(".struct_ops.link")
17+
struct bpf_testmod_ops testmod_1 = {
18+
.test_1 = (void *)test_1,
19+
.test_2 = (void *)test_2
20+
};
21+
22+
SEC(".struct_ops.link")
23+
struct bpf_testmod_ops2 testmod_2 = {
24+
.test_1 = (void *)test_1
25+
};

0 commit comments

Comments
 (0)