Skip to content

Commit 490c99d

Browse files
iii-iborkmann
authored andcommitted
selftests/bpf: Add UAF tests for arena atomics
Check that __sync_*() functions don't cause kernel panics when handling freed arena pages. x86_64 does not support some arena atomics yet, and aarch64 may or may not support them, based on the availability of LSE atomics at run time. Do not enable this test for these architectures for simplicity. Signed-off-by: Ilya Leoshkevich <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent b6349fd commit 490c99d

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,22 @@ static void test_xchg(struct arena_atomics *skel)
146146
ASSERT_EQ(skel->arena->xchg32_result, 1, "xchg32_result");
147147
}
148148

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+
149165
void test_arena_atomics(void)
150166
{
151167
struct arena_atomics *skel;
@@ -180,6 +196,8 @@ void test_arena_atomics(void)
180196
test_cmpxchg(skel);
181197
if (test__start_subtest("xchg"))
182198
test_xchg(skel);
199+
if (test__start_subtest("uaf"))
200+
test_uaf(skel);
183201

184202
cleanup:
185203
arena_atomics__destroy(skel);

tools/testing/selftests/bpf/progs/arena_atomics.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,79 @@ int xchg(const void *ctx)
169169

170170
return 0;
171171
}
172+
173+
__u64 __arena_global uaf_sink;
174+
volatile __u64 __arena_global uaf_recovery_fails;
175+
176+
SEC("syscall")
177+
int uaf(const void *ctx)
178+
{
179+
if (pid != (bpf_get_current_pid_tgid() >> 32))
180+
return 0;
181+
#if defined(ENABLE_ATOMICS_TESTS) && !defined(__TARGET_ARCH_arm64) && \
182+
!defined(__TARGET_ARCH_x86)
183+
__u32 __arena *page32;
184+
__u64 __arena *page64;
185+
void __arena *page;
186+
187+
page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
188+
bpf_arena_free_pages(&arena, page, 1);
189+
uaf_recovery_fails = 24;
190+
191+
page32 = (__u32 __arena *)page;
192+
uaf_sink += __sync_fetch_and_add(page32, 1);
193+
uaf_recovery_fails -= 1;
194+
__sync_add_and_fetch(page32, 1);
195+
uaf_recovery_fails -= 1;
196+
uaf_sink += __sync_fetch_and_sub(page32, 1);
197+
uaf_recovery_fails -= 1;
198+
__sync_sub_and_fetch(page32, 1);
199+
uaf_recovery_fails -= 1;
200+
uaf_sink += __sync_fetch_and_and(page32, 1);
201+
uaf_recovery_fails -= 1;
202+
__sync_and_and_fetch(page32, 1);
203+
uaf_recovery_fails -= 1;
204+
uaf_sink += __sync_fetch_and_or(page32, 1);
205+
uaf_recovery_fails -= 1;
206+
__sync_or_and_fetch(page32, 1);
207+
uaf_recovery_fails -= 1;
208+
uaf_sink += __sync_fetch_and_xor(page32, 1);
209+
uaf_recovery_fails -= 1;
210+
__sync_xor_and_fetch(page32, 1);
211+
uaf_recovery_fails -= 1;
212+
uaf_sink += __sync_val_compare_and_swap(page32, 0, 1);
213+
uaf_recovery_fails -= 1;
214+
uaf_sink += __sync_lock_test_and_set(page32, 1);
215+
uaf_recovery_fails -= 1;
216+
217+
page64 = (__u64 __arena *)page;
218+
uaf_sink += __sync_fetch_and_add(page64, 1);
219+
uaf_recovery_fails -= 1;
220+
__sync_add_and_fetch(page64, 1);
221+
uaf_recovery_fails -= 1;
222+
uaf_sink += __sync_fetch_and_sub(page64, 1);
223+
uaf_recovery_fails -= 1;
224+
__sync_sub_and_fetch(page64, 1);
225+
uaf_recovery_fails -= 1;
226+
uaf_sink += __sync_fetch_and_and(page64, 1);
227+
uaf_recovery_fails -= 1;
228+
__sync_and_and_fetch(page64, 1);
229+
uaf_recovery_fails -= 1;
230+
uaf_sink += __sync_fetch_and_or(page64, 1);
231+
uaf_recovery_fails -= 1;
232+
__sync_or_and_fetch(page64, 1);
233+
uaf_recovery_fails -= 1;
234+
uaf_sink += __sync_fetch_and_xor(page64, 1);
235+
uaf_recovery_fails -= 1;
236+
__sync_xor_and_fetch(page64, 1);
237+
uaf_recovery_fails -= 1;
238+
uaf_sink += __sync_val_compare_and_swap(page64, 0, 1);
239+
uaf_recovery_fails -= 1;
240+
uaf_sink += __sync_lock_test_and_set(page64, 1);
241+
uaf_recovery_fails -= 1;
242+
#endif
243+
244+
return 0;
245+
}
246+
247+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)