xref: /linux/tools/testing/selftests/bpf/prog_tests/arena_atomics.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3 #include <test_progs.h>
4 #include "arena_atomics.skel.h"
5 
6 static void test_add(struct arena_atomics *skel)
7 {
8 	LIBBPF_OPTS(bpf_test_run_opts, topts);
9 	int err, prog_fd;
10 
11 	/* No need to attach it, just run it directly */
12 	prog_fd = bpf_program__fd(skel->progs.add);
13 	err = bpf_prog_test_run_opts(prog_fd, &topts);
14 	if (!ASSERT_OK(err, "test_run_opts err"))
15 		return;
16 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
17 		return;
18 
19 	ASSERT_EQ(skel->arena->add64_value, 3, "add64_value");
20 	ASSERT_EQ(skel->arena->add64_result, 1, "add64_result");
21 
22 	ASSERT_EQ(skel->arena->add32_value, 3, "add32_value");
23 	ASSERT_EQ(skel->arena->add32_result, 1, "add32_result");
24 
25 	ASSERT_EQ(skel->arena->add_stack_value_copy, 3, "add_stack_value");
26 	ASSERT_EQ(skel->arena->add_stack_result, 1, "add_stack_result");
27 
28 	ASSERT_EQ(skel->arena->add_noreturn_value, 3, "add_noreturn_value");
29 }
30 
31 static void test_sub(struct arena_atomics *skel)
32 {
33 	LIBBPF_OPTS(bpf_test_run_opts, topts);
34 	int err, prog_fd;
35 
36 	/* No need to attach it, just run it directly */
37 	prog_fd = bpf_program__fd(skel->progs.sub);
38 	err = bpf_prog_test_run_opts(prog_fd, &topts);
39 	if (!ASSERT_OK(err, "test_run_opts err"))
40 		return;
41 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
42 		return;
43 
44 	ASSERT_EQ(skel->arena->sub64_value, -1, "sub64_value");
45 	ASSERT_EQ(skel->arena->sub64_result, 1, "sub64_result");
46 
47 	ASSERT_EQ(skel->arena->sub32_value, -1, "sub32_value");
48 	ASSERT_EQ(skel->arena->sub32_result, 1, "sub32_result");
49 
50 	ASSERT_EQ(skel->arena->sub_stack_value_copy, -1, "sub_stack_value");
51 	ASSERT_EQ(skel->arena->sub_stack_result, 1, "sub_stack_result");
52 
53 	ASSERT_EQ(skel->arena->sub_noreturn_value, -1, "sub_noreturn_value");
54 }
55 
56 static void test_and(struct arena_atomics *skel)
57 {
58 	LIBBPF_OPTS(bpf_test_run_opts, topts);
59 	int err, prog_fd;
60 
61 	/* No need to attach it, just run it directly */
62 	prog_fd = bpf_program__fd(skel->progs.and);
63 	err = bpf_prog_test_run_opts(prog_fd, &topts);
64 	if (!ASSERT_OK(err, "test_run_opts err"))
65 		return;
66 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
67 		return;
68 
69 	ASSERT_EQ(skel->arena->and64_value, 0x010ull << 32, "and64_value");
70 	ASSERT_EQ(skel->arena->and32_value, 0x010, "and32_value");
71 }
72 
73 static void test_or(struct arena_atomics *skel)
74 {
75 	LIBBPF_OPTS(bpf_test_run_opts, topts);
76 	int err, prog_fd;
77 
78 	/* No need to attach it, just run it directly */
79 	prog_fd = bpf_program__fd(skel->progs.or);
80 	err = bpf_prog_test_run_opts(prog_fd, &topts);
81 	if (!ASSERT_OK(err, "test_run_opts err"))
82 		return;
83 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
84 		return;
85 
86 	ASSERT_EQ(skel->arena->or64_value, 0x111ull << 32, "or64_value");
87 	ASSERT_EQ(skel->arena->or32_value, 0x111, "or32_value");
88 }
89 
90 static void test_xor(struct arena_atomics *skel)
91 {
92 	LIBBPF_OPTS(bpf_test_run_opts, topts);
93 	int err, prog_fd;
94 
95 	/* No need to attach it, just run it directly */
96 	prog_fd = bpf_program__fd(skel->progs.xor);
97 	err = bpf_prog_test_run_opts(prog_fd, &topts);
98 	if (!ASSERT_OK(err, "test_run_opts err"))
99 		return;
100 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
101 		return;
102 
103 	ASSERT_EQ(skel->arena->xor64_value, 0x101ull << 32, "xor64_value");
104 	ASSERT_EQ(skel->arena->xor32_value, 0x101, "xor32_value");
105 }
106 
107 static void test_cmpxchg(struct arena_atomics *skel)
108 {
109 	LIBBPF_OPTS(bpf_test_run_opts, topts);
110 	int err, prog_fd;
111 
112 	/* No need to attach it, just run it directly */
113 	prog_fd = bpf_program__fd(skel->progs.cmpxchg);
114 	err = bpf_prog_test_run_opts(prog_fd, &topts);
115 	if (!ASSERT_OK(err, "test_run_opts err"))
116 		return;
117 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
118 		return;
119 
120 	ASSERT_EQ(skel->arena->cmpxchg64_value, 2, "cmpxchg64_value");
121 	ASSERT_EQ(skel->arena->cmpxchg64_result_fail, 1, "cmpxchg_result_fail");
122 	ASSERT_EQ(skel->arena->cmpxchg64_result_succeed, 1, "cmpxchg_result_succeed");
123 
124 	ASSERT_EQ(skel->arena->cmpxchg32_value, 2, "lcmpxchg32_value");
125 	ASSERT_EQ(skel->arena->cmpxchg32_result_fail, 1, "cmpxchg_result_fail");
126 	ASSERT_EQ(skel->arena->cmpxchg32_result_succeed, 1, "cmpxchg_result_succeed");
127 }
128 
129 static void test_xchg(struct arena_atomics *skel)
130 {
131 	LIBBPF_OPTS(bpf_test_run_opts, topts);
132 	int err, prog_fd;
133 
134 	/* No need to attach it, just run it directly */
135 	prog_fd = bpf_program__fd(skel->progs.xchg);
136 	err = bpf_prog_test_run_opts(prog_fd, &topts);
137 	if (!ASSERT_OK(err, "test_run_opts err"))
138 		return;
139 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
140 		return;
141 
142 	ASSERT_EQ(skel->arena->xchg64_value, 2, "xchg64_value");
143 	ASSERT_EQ(skel->arena->xchg64_result, 1, "xchg64_result");
144 
145 	ASSERT_EQ(skel->arena->xchg32_value, 2, "xchg32_value");
146 	ASSERT_EQ(skel->arena->xchg32_result, 1, "xchg32_result");
147 }
148 
149 static void test_uaf(struct arena_atomics *skel)
150 {
151 	LIBBPF_OPTS(bpf_test_run_opts, topts);
152 	int err, prog_fd;
153 
154 	/* No need to attach it, just run it directly */
155 	prog_fd = bpf_program__fd(skel->progs.uaf);
156 	err = bpf_prog_test_run_opts(prog_fd, &topts);
157 	if (!ASSERT_OK(err, "test_run_opts err"))
158 		return;
159 	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
160 		return;
161 
162 	ASSERT_EQ(skel->arena->uaf_recovery_fails, 0, "uaf_recovery_fails");
163 }
164 
165 void test_arena_atomics(void)
166 {
167 	struct arena_atomics *skel;
168 	int err;
169 
170 	skel = arena_atomics__open();
171 	if (!ASSERT_OK_PTR(skel, "arena atomics skeleton open"))
172 		return;
173 
174 	if (skel->data->skip_tests) {
175 		printf("%s:SKIP:no ENABLE_ATOMICS_TESTS or no addr_space_cast support in clang",
176 		       __func__);
177 		test__skip();
178 		goto cleanup;
179 	}
180 	err = arena_atomics__load(skel);
181 	if (!ASSERT_OK(err, "arena atomics skeleton load"))
182 		return;
183 	skel->bss->pid = getpid();
184 
185 	if (test__start_subtest("add"))
186 		test_add(skel);
187 	if (test__start_subtest("sub"))
188 		test_sub(skel);
189 	if (test__start_subtest("and"))
190 		test_and(skel);
191 	if (test__start_subtest("or"))
192 		test_or(skel);
193 	if (test__start_subtest("xor"))
194 		test_xor(skel);
195 	if (test__start_subtest("cmpxchg"))
196 		test_cmpxchg(skel);
197 	if (test__start_subtest("xchg"))
198 		test_xchg(skel);
199 	if (test__start_subtest("uaf"))
200 		test_uaf(skel);
201 
202 cleanup:
203 	arena_atomics__destroy(skel);
204 }
205