Commit c1b93c07 authored by Eduard Zingerman's avatar Eduard Zingerman Committed by Andrii Nakryiko

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: default avatarEduard Zingerman <eddyz87@gmail.com>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20240306104529.6453-7-eddyz87@gmail.com
parent c8617e8b
...@@ -611,6 +611,29 @@ struct bpf_struct_ops bpf_bpf_testmod_ops = { ...@@ -611,6 +611,29 @@ struct bpf_struct_ops bpf_bpf_testmod_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int bpf_dummy_reg2(void *kdata)
{
struct bpf_testmod_ops2 *ops = kdata;
ops->test_1();
return 0;
}
static struct bpf_testmod_ops2 __bpf_testmod_ops2 = {
.test_1 = bpf_testmod_test_1,
};
struct bpf_struct_ops bpf_testmod_ops2 = {
.verifier_ops = &bpf_testmod_verifier_ops,
.init = bpf_testmod_ops_init,
.init_member = bpf_testmod_ops_init_member,
.reg = bpf_dummy_reg2,
.unreg = bpf_dummy_unreg,
.cfi_stubs = &__bpf_testmod_ops2,
.name = "bpf_testmod_ops2",
.owner = THIS_MODULE,
};
extern int bpf_fentry_test1(int a); extern int bpf_fentry_test1(int a);
static int bpf_testmod_init(void) static int bpf_testmod_init(void)
...@@ -622,6 +645,7 @@ static int bpf_testmod_init(void) ...@@ -622,6 +645,7 @@ static int bpf_testmod_init(void)
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_testmod_kfunc_set); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_testmod_kfunc_set);
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &bpf_testmod_kfunc_set); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &bpf_testmod_kfunc_set);
ret = ret ?: register_bpf_struct_ops(&bpf_bpf_testmod_ops, bpf_testmod_ops); ret = ret ?: register_bpf_struct_ops(&bpf_bpf_testmod_ops, bpf_testmod_ops);
ret = ret ?: register_bpf_struct_ops(&bpf_testmod_ops2, bpf_testmod_ops2);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (bpf_fentry_test1(0) < 0) if (bpf_fentry_test1(0) < 0)
......
...@@ -89,4 +89,8 @@ struct bpf_testmod_ops { ...@@ -89,4 +89,8 @@ struct bpf_testmod_ops {
int (*tramp_40)(int value); int (*tramp_40)(int value);
}; };
struct bpf_testmod_ops2 {
int (*test_1)(void);
};
#endif /* _BPF_TESTMOD_H */ #endif /* _BPF_TESTMOD_H */
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
#include "bad_struct_ops.skel.h"
static void invalid_prog_reuse(void)
{
struct bad_struct_ops *skel;
char *log = NULL;
int err;
skel = bad_struct_ops__open();
if (!ASSERT_OK_PTR(skel, "bad_struct_ops__open"))
return;
if (start_libbpf_log_capture())
goto cleanup;
err = bad_struct_ops__load(skel);
log = stop_libbpf_log_capture();
ASSERT_ERR(err, "bad_struct_ops__load should fail");
ASSERT_HAS_SUBSTR(log,
"struct_ops init_kern testmod_2 func ptr test_1: invalid reuse of prog test_1",
"expected init_kern message");
cleanup:
free(log);
bad_struct_ops__destroy(skel);
}
void test_bad_struct_ops(void)
{
if (test__start_subtest("invalid_prog_reuse"))
invalid_prog_reuse();
}
// SPDX-License-Identifier: GPL-2.0
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "../bpf_testmod/bpf_testmod.h"
char _license[] SEC("license") = "GPL";
SEC("struct_ops/test_1")
int BPF_PROG(test_1) { return 0; }
SEC("struct_ops/test_2")
int BPF_PROG(test_2) { return 0; }
SEC(".struct_ops.link")
struct bpf_testmod_ops testmod_1 = {
.test_1 = (void *)test_1,
.test_2 = (void *)test_2
};
SEC(".struct_ops.link")
struct bpf_testmod_ops2 testmod_2 = {
.test_1 = (void *)test_1
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment