Skip to content

Commit cada0bd

Browse files
Martin KaFai LauAlexei Starovoitov
authored andcommitted
selftests/bpf: Test epilogue patching when the main prog has multiple BPF_EXIT
This patch tests the epilogue patching when the main prog has multiple BPF_EXIT. The verifier should have patched the 2nd (and later) BPF_EXIT with a BPF_JA that goes back to the earlier patched epilogue instructions. Acked-by: Eduard Zingerman <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 42fdbbd commit cada0bd

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

tools/testing/selftests/bpf/prog_tests/pro_epilogue.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "pro_epilogue.skel.h"
66
#include "epilogue_tailcall.skel.h"
77
#include "pro_epilogue_goto_start.skel.h"
8+
#include "epilogue_exit.skel.h"
89

910
struct st_ops_args {
1011
__u64 a;
@@ -53,6 +54,7 @@ void test_pro_epilogue(void)
5354
{
5455
RUN_TESTS(pro_epilogue);
5556
RUN_TESTS(pro_epilogue_goto_start);
57+
RUN_TESTS(epilogue_exit);
5658
if (test__start_subtest("tailcall"))
5759
test_tailcall();
5860
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3+
4+
#include <vmlinux.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include "bpf_misc.h"
7+
#include "../bpf_testmod/bpf_testmod.h"
8+
#include "../bpf_testmod/bpf_testmod_kfunc.h"
9+
10+
char _license[] SEC("license") = "GPL";
11+
12+
__success
13+
/* save __u64 *ctx to stack */
14+
__xlated("0: *(u64 *)(r10 -8) = r1")
15+
/* main prog */
16+
__xlated("1: r1 = *(u64 *)(r1 +0)")
17+
__xlated("2: r2 = *(u64 *)(r1 +0)")
18+
__xlated("3: r3 = 0")
19+
__xlated("4: r4 = 1")
20+
__xlated("5: if r2 == 0x0 goto pc+10")
21+
__xlated("6: r0 = 0")
22+
__xlated("7: *(u64 *)(r1 +0) = r3")
23+
/* epilogue */
24+
__xlated("8: r1 = *(u64 *)(r10 -8)")
25+
__xlated("9: r1 = *(u64 *)(r1 +0)")
26+
__xlated("10: r6 = *(u64 *)(r1 +0)")
27+
__xlated("11: r6 += 10000")
28+
__xlated("12: *(u64 *)(r1 +0) = r6")
29+
__xlated("13: r0 = r6")
30+
__xlated("14: r0 *= 2")
31+
__xlated("15: exit")
32+
/* 2nd part of the main prog after the first exit */
33+
__xlated("16: *(u64 *)(r1 +0) = r4")
34+
__xlated("17: r0 = 1")
35+
/* Clear the r1 to ensure it does not have
36+
* off-by-1 error and ensure it jumps back to the
37+
* beginning of epilogue which initializes
38+
* the r1 with the ctx ptr.
39+
*/
40+
__xlated("18: r1 = 0")
41+
__xlated("19: gotol pc-12")
42+
SEC("struct_ops/test_epilogue_exit")
43+
__naked int test_epilogue_exit(void)
44+
{
45+
asm volatile (
46+
"r1 = *(u64 *)(r1 +0);"
47+
"r2 = *(u64 *)(r1 +0);"
48+
"r3 = 0;"
49+
"r4 = 1;"
50+
"if r2 == 0 goto +3;"
51+
"r0 = 0;"
52+
"*(u64 *)(r1 + 0) = r3;"
53+
"exit;"
54+
"*(u64 *)(r1 + 0) = r4;"
55+
"r0 = 1;"
56+
"r1 = 0;"
57+
"exit;"
58+
::: __clobber_all);
59+
}
60+
61+
SEC(".struct_ops.link")
62+
struct bpf_testmod_st_ops epilogue_exit = {
63+
.test_epilogue = (void *)test_epilogue_exit,
64+
};
65+
66+
SEC("syscall")
67+
__retval(20000)
68+
int syscall_epilogue_exit0(void *ctx)
69+
{
70+
struct st_ops_args args = { .a = 1 };
71+
72+
return bpf_kfunc_st_ops_test_epilogue(&args);
73+
}
74+
75+
SEC("syscall")
76+
__retval(20002)
77+
int syscall_epilogue_exit1(void *ctx)
78+
{
79+
struct st_ops_args args = {};
80+
81+
return bpf_kfunc_st_ops_test_epilogue(&args);
82+
}

0 commit comments

Comments
 (0)