Skip to content

Commit 3d895ed

Browse files
anakryikoNobody
authored andcommitted
selftests/bpf: add custom SEC() handling selftest
Add a selftest validating various aspects of libbpf's handling of custom SEC() handlers. It also demonstrates how libraries can ensure very early callbacks registration and unregistration using __attribute__((constructor))/__attribute__((destructor)) functions. Signed-off-by: Andrii Nakryiko <[email protected]>
1 parent 730f821 commit 3d895ed

File tree

2 files changed

+187
-0
lines changed

2 files changed

+187
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2022 Facebook */
3+
4+
#include <test_progs.h>
5+
#include "test_custom_sec_handlers.skel.h"
6+
7+
#define COOKIE_ABC1 1
8+
#define COOKIE_ABC2 2
9+
#define COOKIE_CUSTOM 3
10+
#define COOKIE_FALLBACK 4
11+
12+
static int custom_init_prog(struct bpf_program *prog, long cookie)
13+
{
14+
if (cookie == COOKIE_ABC1)
15+
bpf_program__set_autoload(prog, false);
16+
17+
return 0;
18+
}
19+
20+
static int custom_preload_prog(struct bpf_program *prog,
21+
struct bpf_prog_load_opts *opts, long cookie)
22+
{
23+
return 0;
24+
}
25+
26+
static int custom_attach_prog(const struct bpf_program *prog, long cookie,
27+
struct bpf_link **link)
28+
{
29+
switch (cookie) {
30+
case COOKIE_ABC2:
31+
*link = bpf_program__attach_raw_tracepoint(prog, "sys_enter");
32+
return libbpf_get_error(*link);
33+
case COOKIE_CUSTOM:
34+
*link = bpf_program__attach_tracepoint(prog, "syscalls", "sys_enter_nanosleep");
35+
return libbpf_get_error(*link);
36+
case COOKIE_FALLBACK:
37+
/* no auto-attach for SEC("xyz") */
38+
*link = NULL;
39+
return 0;
40+
default:
41+
ASSERT_FALSE(true, "unexpected cookie");
42+
return -EINVAL;
43+
}
44+
}
45+
46+
static int abc1_id;
47+
static int abc2_id;
48+
static int custom_id;
49+
static int fallback_id;
50+
51+
__attribute__((constructor))
52+
static void register_sec_handlers(void)
53+
{
54+
abc1_id = libbpf_register_prog_handler("abc",
55+
BPF_PROG_TYPE_RAW_TRACEPOINT, 0,
56+
custom_init_prog, custom_preload_prog,
57+
custom_attach_prog,
58+
COOKIE_ABC1, NULL);
59+
abc2_id = libbpf_register_prog_handler("abc/",
60+
BPF_PROG_TYPE_RAW_TRACEPOINT, 0,
61+
custom_init_prog, custom_preload_prog,
62+
custom_attach_prog,
63+
COOKIE_ABC2, NULL);
64+
custom_id = libbpf_register_prog_handler("custom+",
65+
BPF_PROG_TYPE_TRACEPOINT, 0,
66+
custom_init_prog, custom_preload_prog,
67+
custom_attach_prog,
68+
COOKIE_CUSTOM, NULL);
69+
}
70+
71+
__attribute__((destructor))
72+
static void unregister_sec_handlers(void)
73+
{
74+
libbpf_unregister_prog_handler(abc1_id);
75+
libbpf_unregister_prog_handler(abc2_id);
76+
libbpf_unregister_prog_handler(custom_id);
77+
}
78+
79+
void test_custom_sec_handlers(void)
80+
{
81+
struct test_custom_sec_handlers* skel;
82+
int err;
83+
84+
ASSERT_GT(abc1_id, 0, "abc1_id");
85+
ASSERT_GT(abc2_id, 0, "abc2_id");
86+
ASSERT_GT(custom_id, 0, "custom_id");
87+
88+
fallback_id = libbpf_register_prog_handler(NULL, /* fallback handler */
89+
BPF_PROG_TYPE_KPROBE, 0,
90+
custom_init_prog, custom_preload_prog,
91+
custom_attach_prog,
92+
COOKIE_FALLBACK, NULL);
93+
if (!ASSERT_GT(fallback_id, 0, "fallback_id"))
94+
return;
95+
96+
/* open skeleton and validate assumptions */
97+
skel = test_custom_sec_handlers__open();
98+
if (!ASSERT_OK_PTR(skel, "skel_open"))
99+
goto cleanup;
100+
101+
ASSERT_EQ(bpf_program__type(skel->progs.abc1), BPF_PROG_TYPE_RAW_TRACEPOINT, "abc1_type");
102+
ASSERT_FALSE(bpf_program__autoload(skel->progs.abc1), "abc1_autoload");
103+
104+
ASSERT_EQ(bpf_program__type(skel->progs.abc2), BPF_PROG_TYPE_RAW_TRACEPOINT, "abc2_type");
105+
ASSERT_EQ(bpf_program__type(skel->progs.custom1), BPF_PROG_TYPE_TRACEPOINT, "custom1_type");
106+
ASSERT_EQ(bpf_program__type(skel->progs.custom2), BPF_PROG_TYPE_TRACEPOINT, "custom2_type");
107+
ASSERT_EQ(bpf_program__type(skel->progs.xyz), BPF_PROG_TYPE_KPROBE, "xyz_type");
108+
109+
skel->rodata->my_pid = getpid();
110+
111+
/* now attempt to load everything */
112+
err = test_custom_sec_handlers__load(skel);
113+
if (!ASSERT_OK(err, "skel_load"))
114+
goto cleanup;
115+
116+
/* now try to auto-attach everything */
117+
err = test_custom_sec_handlers__attach(skel);
118+
if (!ASSERT_OK(err, "skel_attach"))
119+
goto cleanup;
120+
121+
/* trigger programs */
122+
usleep(1);
123+
124+
/* SEC("abc") is set to not auto-loaded */
125+
ASSERT_FALSE(skel->bss->abc1_called, "abc1_called");
126+
ASSERT_TRUE(skel->bss->abc2_called, "abc2_called");
127+
ASSERT_TRUE(skel->bss->custom1_called, "custom1_called");
128+
ASSERT_TRUE(skel->bss->custom2_called, "custom2_called");
129+
/* SEC("xyz") shouldn't be auto-attached */
130+
ASSERT_FALSE(skel->bss->xyz_called, "xyz_called");
131+
132+
cleanup:
133+
test_custom_sec_handlers__destroy(skel);
134+
135+
ASSERT_OK(libbpf_unregister_prog_handler(fallback_id), "unregister_fallback");
136+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2022 Facebook */
3+
4+
#include "vmlinux.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include <bpf/bpf_tracing.h>
7+
8+
const volatile int my_pid;
9+
10+
bool abc1_called;
11+
bool abc2_called;
12+
bool custom1_called;
13+
bool custom2_called;
14+
bool xyz_called;
15+
16+
SEC("abc")
17+
int abc1(void *ctx)
18+
{
19+
abc1_called = true;
20+
return 0;
21+
}
22+
23+
SEC("abc/whatever")
24+
int abc2(void *ctx)
25+
{
26+
abc2_called = true;
27+
return 0;
28+
}
29+
30+
SEC("custom")
31+
int custom1(void *ctx)
32+
{
33+
custom1_called = true;
34+
return 0;
35+
}
36+
37+
SEC("custom/something")
38+
int custom2(void *ctx)
39+
{
40+
custom2_called = true;
41+
return 0;
42+
}
43+
44+
SEC("xyz/blah")
45+
int xyz(void *ctx)
46+
{
47+
xyz_called = true;
48+
return 0;
49+
}
50+
51+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)