1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "missed_kprobe.skel.h"
4 #include "missed_kprobe_recursion.skel.h"
5 #include "missed_tp_recursion.skel.h"
6
7 /*
8 * Putting kprobe on bpf_fentry_test1 that calls bpf_kfunc_common_test
9 * kfunc, which has also kprobe on. The latter won't get triggered due
10 * to kprobe recursion check and kprobe missed counter is incremented.
11 */
test_missed_perf_kprobe(void)12 static void test_missed_perf_kprobe(void)
13 {
14 LIBBPF_OPTS(bpf_test_run_opts, topts);
15 struct bpf_link_info info = {};
16 struct missed_kprobe *skel;
17 __u32 len = sizeof(info);
18 int err, prog_fd;
19
20 skel = missed_kprobe__open_and_load();
21 if (!ASSERT_OK_PTR(skel, "missed_kprobe__open_and_load"))
22 goto cleanup;
23
24 err = missed_kprobe__attach(skel);
25 if (!ASSERT_OK(err, "missed_kprobe__attach"))
26 goto cleanup;
27
28 prog_fd = bpf_program__fd(skel->progs.trigger);
29 err = bpf_prog_test_run_opts(prog_fd, &topts);
30 ASSERT_OK(err, "test_run");
31 ASSERT_EQ(topts.retval, 0, "test_run");
32
33 err = bpf_link_get_info_by_fd(bpf_link__fd(skel->links.test2), &info, &len);
34 if (!ASSERT_OK(err, "bpf_link_get_info_by_fd"))
35 goto cleanup;
36
37 ASSERT_EQ(info.type, BPF_LINK_TYPE_PERF_EVENT, "info.type");
38 ASSERT_EQ(info.perf_event.type, BPF_PERF_EVENT_KPROBE, "info.perf_event.type");
39 ASSERT_EQ(info.perf_event.kprobe.missed, 1, "info.perf_event.kprobe.missed");
40
41 cleanup:
42 missed_kprobe__destroy(skel);
43 }
44
get_missed_count(int fd)45 static __u64 get_missed_count(int fd)
46 {
47 struct bpf_prog_info info = {};
48 __u32 len = sizeof(info);
49 int err;
50
51 err = bpf_prog_get_info_by_fd(fd, &info, &len);
52 if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd"))
53 return (__u64) -1;
54 return info.recursion_misses;
55 }
56
57 /*
58 * Putting kprobe.multi on bpf_fentry_test1 that calls bpf_kfunc_common_test
59 * kfunc which has 3 perf event kprobes and 1 kprobe.multi attached.
60 *
61 * Because fprobe (kprobe.multi attach layear) does not have strict recursion
62 * check the kprobe's bpf_prog_active check is hit for test2-5.
63 */
test_missed_kprobe_recursion(void)64 static void test_missed_kprobe_recursion(void)
65 {
66 LIBBPF_OPTS(bpf_test_run_opts, topts);
67 struct missed_kprobe_recursion *skel;
68 int err, prog_fd;
69
70 skel = missed_kprobe_recursion__open_and_load();
71 if (!ASSERT_OK_PTR(skel, "missed_kprobe_recursion__open_and_load"))
72 goto cleanup;
73
74 err = missed_kprobe_recursion__attach(skel);
75 if (!ASSERT_OK(err, "missed_kprobe_recursion__attach"))
76 goto cleanup;
77
78 prog_fd = bpf_program__fd(skel->progs.trigger);
79 err = bpf_prog_test_run_opts(prog_fd, &topts);
80 ASSERT_OK(err, "test_run");
81 ASSERT_EQ(topts.retval, 0, "test_run");
82
83 ASSERT_EQ(get_missed_count(bpf_program__fd(skel->progs.test1)), 0, "test1_recursion_misses");
84 ASSERT_GE(get_missed_count(bpf_program__fd(skel->progs.test2)), 1, "test2_recursion_misses");
85 ASSERT_GE(get_missed_count(bpf_program__fd(skel->progs.test3)), 1, "test3_recursion_misses");
86 ASSERT_GE(get_missed_count(bpf_program__fd(skel->progs.test4)), 1, "test4_recursion_misses");
87 ASSERT_GE(get_missed_count(bpf_program__fd(skel->progs.test5)), 1, "test5_recursion_misses");
88
89 cleanup:
90 missed_kprobe_recursion__destroy(skel);
91 }
92
93 /*
94 * Putting kprobe on bpf_fentry_test1 that calls bpf_printk and invokes
95 * bpf_trace_printk tracepoint. The bpf_trace_printk tracepoint has test[234]
96 * programs attached to it.
97 *
98 * Because kprobe execution goes through bpf_prog_active check, programs
99 * attached to the tracepoint will fail the recursion check and increment
100 * the recursion_misses stats.
101 */
test_missed_tp_recursion(void)102 static void test_missed_tp_recursion(void)
103 {
104 LIBBPF_OPTS(bpf_test_run_opts, topts);
105 struct missed_tp_recursion *skel;
106 int err, prog_fd;
107
108 skel = missed_tp_recursion__open_and_load();
109 if (!ASSERT_OK_PTR(skel, "missed_tp_recursion__open_and_load"))
110 goto cleanup;
111
112 err = missed_tp_recursion__attach(skel);
113 if (!ASSERT_OK(err, "missed_tp_recursion__attach"))
114 goto cleanup;
115
116 prog_fd = bpf_program__fd(skel->progs.trigger);
117 err = bpf_prog_test_run_opts(prog_fd, &topts);
118 ASSERT_OK(err, "test_run");
119 ASSERT_EQ(topts.retval, 0, "test_run");
120
121 ASSERT_EQ(get_missed_count(bpf_program__fd(skel->progs.test1)), 0, "test1_recursion_misses");
122 ASSERT_EQ(get_missed_count(bpf_program__fd(skel->progs.test2)), 1, "test2_recursion_misses");
123 ASSERT_EQ(get_missed_count(bpf_program__fd(skel->progs.test3)), 1, "test3_recursion_misses");
124 ASSERT_EQ(get_missed_count(bpf_program__fd(skel->progs.test4)), 1, "test4_recursion_misses");
125
126 cleanup:
127 missed_tp_recursion__destroy(skel);
128 }
129
test_missed(void)130 void test_missed(void)
131 {
132 if (test__start_subtest("perf_kprobe"))
133 test_missed_perf_kprobe();
134 if (test__start_subtest("kprobe_recursion"))
135 test_missed_kprobe_recursion();
136 if (test__start_subtest("tp_recursion"))
137 test_missed_tp_recursion();
138 }
139