Skip to content

Commit 1230ea5

Browse files
etsalKernel Patches Daemon
authored andcommitted
selftests/bpf: add tests for the arena offset of globals
Add tests for the new libbpf globals arena offset logic. The tests cover the case of globals being as large as the arena itself, and being smaller than the arena. In that case, the data is placed at the end of the arena, and the beginning of the arena is free. Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
1 parent 3b7f21f commit 1230ea5

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "verifier_and.skel.h"
77
#include "verifier_arena.skel.h"
88
#include "verifier_arena_large.skel.h"
9+
#include "verifier_arena_globals1.skel.h"
10+
#include "verifier_arena_globals2.skel.h"
911
#include "verifier_array_access.skel.h"
1012
#include "verifier_async_cb_context.skel.h"
1113
#include "verifier_basic_stack.skel.h"
@@ -147,6 +149,8 @@ static void run_tests_aux(const char *skel_name,
147149
void test_verifier_and(void) { RUN(verifier_and); }
148150
void test_verifier_arena(void) { RUN(verifier_arena); }
149151
void test_verifier_arena_large(void) { RUN(verifier_arena_large); }
152+
void test_verifier_arena_globals1(void) { RUN(verifier_arena_globals1); }
153+
void test_verifier_arena_globals2(void) { RUN(verifier_arena_globals2); }
150154
void test_verifier_basic_stack(void) { RUN(verifier_basic_stack); }
151155
void test_verifier_bitfield_write(void) { RUN(verifier_bitfield_write); }
152156
void test_verifier_bounds(void) { RUN(verifier_bounds); }
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
3+
4+
#define BPF_NO_KFUNC_PROTOTYPES
5+
#include <vmlinux.h>
6+
#include <bpf/bpf_helpers.h>
7+
#include <bpf/bpf_tracing.h>
8+
#include "bpf_experimental.h"
9+
#include "bpf_arena_common.h"
10+
#include "bpf_misc.h"
11+
12+
#define ARENA_PAGES (1UL<< (32 - 12))
13+
#define GLOBAL_PAGES (16)
14+
15+
struct {
16+
__uint(type, BPF_MAP_TYPE_ARENA);
17+
__uint(map_flags, BPF_F_MMAPABLE);
18+
__uint(max_entries, ARENA_PAGES);
19+
#ifdef __TARGET_ARCH_arm64
20+
__ulong(map_extra, (1ull << 32) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
21+
#else
22+
__ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
23+
#endif
24+
} arena SEC(".maps");
25+
26+
/*
27+
* Global data, to be placed at the end of the arena.
28+
*/
29+
char __arena global_data[GLOBAL_PAGES][PAGE_SIZE];
30+
31+
SEC("syscall")
32+
__success __retval(0)
33+
int check_reserve1(void *ctx)
34+
{
35+
#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
36+
__u8 __arena *guard, *globals;
37+
int ret;
38+
39+
guard = (void __arena *)arena_base(&arena);
40+
globals = (void __arena *)(arena_base(&arena) + (ARENA_PAGES - GLOBAL_PAGES) * PAGE_SIZE);
41+
42+
/* Reserve the region we've offset the globals by. */
43+
ret = bpf_arena_reserve_pages(&arena, guard, ARENA_PAGES - GLOBAL_PAGES);
44+
if (ret)
45+
return 1;
46+
47+
/* Make sure the globals are in the expected offset. */
48+
ret = bpf_arena_reserve_pages(&arena, globals, 1);
49+
if (!ret)
50+
return 2;
51+
#endif
52+
return 0;
53+
}
54+
55+
/*
56+
* Relocation check by reading directly into the global data w/o using symbols.
57+
*/
58+
SEC("syscall")
59+
__success __retval(0)
60+
int check_relocation(void *ctx)
61+
{
62+
#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
63+
const u8 magic = 0xfa;
64+
u8 __arena *ptr;
65+
66+
global_data[GLOBAL_PAGES - 1][PAGE_SIZE / 2] = magic;
67+
ptr = (u8 __arena *)((u64)(ARENA_PAGES * PAGE_SIZE - PAGE_SIZE / 2));
68+
if (*ptr != magic)
69+
return 1;
70+
71+
#endif
72+
return 0;
73+
}
74+
75+
char _license[] SEC("license") = "GPL";
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
3+
4+
#define BPF_NO_KFUNC_PROTOTYPES
5+
#include <vmlinux.h>
6+
#include <bpf/bpf_helpers.h>
7+
#include <bpf/bpf_tracing.h>
8+
#include "bpf_misc.h"
9+
#include "bpf_experimental.h"
10+
#include "bpf_arena_common.h"
11+
12+
#define ARENA_PAGES (32)
13+
14+
struct {
15+
__uint(type, BPF_MAP_TYPE_ARENA);
16+
__uint(map_flags, BPF_F_MMAPABLE);
17+
__uint(max_entries, ARENA_PAGES);
18+
#ifdef __TARGET_ARCH_arm64
19+
__ulong(map_extra, (1ull << 32) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
20+
#else
21+
__ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
22+
#endif
23+
} arena SEC(".maps");
24+
25+
/*
26+
* Fill the entire arena with global data.
27+
* The offset into the arena should be 0.
28+
*/
29+
char __arena global_data[PAGE_SIZE][ARENA_PAGES];
30+
31+
SEC("syscall")
32+
__success __retval(0)
33+
int check_reserve2(void *ctx)
34+
{
35+
#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
36+
void __arena *guard;
37+
int ret;
38+
39+
guard = (void __arena *)arena_base(&arena);
40+
41+
/* Make sure the data at offset 0 case is properly handled. */
42+
ret = bpf_arena_reserve_pages(&arena, guard, 1);
43+
if (!ret)
44+
return 1;
45+
#endif
46+
return 0;
47+
}
48+
49+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)