Skip to content

Commit 69324ab

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 all three cases: The globals being small enough to be placed at the maximum possible offset, being as large as the arena itself and being placed at the very beginning, and requiring an intermediate offset into the arena. Signed-off-by: Emil Tsalapatis <[email protected]>
1 parent 3084a67 commit 69324ab

File tree

4 files changed

+176
-0
lines changed

4 files changed

+176
-0
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
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"
11+
#include "verifier_arena_globals3.skel.h"
912
#include "verifier_array_access.skel.h"
1013
#include "verifier_async_cb_context.skel.h"
1114
#include "verifier_basic_stack.skel.h"
@@ -147,6 +150,9 @@ static void run_tests_aux(const char *skel_name,
147150
void test_verifier_and(void) { RUN(verifier_and); }
148151
void test_verifier_arena(void) { RUN(verifier_arena); }
149152
void test_verifier_arena_large(void) { RUN(verifier_arena_large); }
153+
void test_verifier_arena_globals1(void) { RUN(verifier_arena_globals1); }
154+
void test_verifier_arena_globals2(void) { RUN(verifier_arena_globals2); }
155+
void test_verifier_arena_globals3(void) { RUN(verifier_arena_globals3); }
150156
void test_verifier_basic_stack(void) { RUN(verifier_basic_stack); }
151157
void test_verifier_bitfield_write(void) { RUN(verifier_bitfield_write); }
152158
void test_verifier_bounds(void) { RUN(verifier_bounds); }
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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 (64)
13+
14+
/* Set in libbpf. */
15+
#define GLOBALS_PGOFF (16)
16+
17+
struct {
18+
__uint(type, BPF_MAP_TYPE_ARENA);
19+
__uint(map_flags, BPF_F_MMAPABLE);
20+
__uint(max_entries, ARENA_PAGES); /* Arena of 64 pages (standard offset is 16 pages) */
21+
#ifdef __TARGET_ARCH_arm64
22+
__ulong(map_extra, (1ull << 32) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
23+
#else
24+
__ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
25+
#endif
26+
} arena SEC(".maps");
27+
28+
/*
29+
* Global data small enough that we can apply the maximum
30+
* offset into the arena. Userspace will also use this to
31+
* ensure the offset doesn't unexpectedly change from
32+
* under us.
33+
*/
34+
char __arena global_data[PAGE_SIZE][ARENA_PAGES - GLOBALS_PGOFF];
35+
36+
SEC("syscall")
37+
__success __retval(0)
38+
int check_reserve1(void *ctx)
39+
{
40+
#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
41+
__u8 __arena *guard, *globals;
42+
int ret;
43+
44+
guard = (void __arena *)arena_base(&arena);
45+
globals = (void __arena *)(arena_base(&arena) + GLOBALS_PGOFF * PAGE_SIZE);
46+
47+
/* Reserve the region we've offset the globals by. */
48+
ret = bpf_arena_reserve_pages(&arena, guard, GLOBALS_PGOFF);
49+
if (ret)
50+
return 1;
51+
52+
/* Make sure the globals are placed GLOBALS_PGOFF pages in. */
53+
ret = bpf_arena_reserve_pages(&arena, globals, 1);
54+
if (!ret)
55+
return 2;
56+
#endif
57+
return 0;
58+
}
59+
60+
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); /* Arena of 32 pages (standard offset is 16 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";
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
#define ARENA_AVAIL_PAGES (6)
15+
16+
struct {
17+
__uint(type, BPF_MAP_TYPE_ARENA);
18+
__uint(map_flags, BPF_F_MMAPABLE);
19+
__uint(max_entries, ARENA_PAGES); /* Arena of 32 pages (standard offset is 16 pages) */
20+
#ifdef __TARGET_ARCH_arm64
21+
__ulong(map_extra, (1ull << 32) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
22+
#else
23+
__ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * ARENA_PAGES + 1));
24+
#endif
25+
} arena SEC(".maps");
26+
27+
/*
28+
* Enough global data to fill most of the arena. Force libbpf to
29+
* adjust the offset into the arena enough for the data to fit.
30+
*/
31+
32+
char __arena global_data[PAGE_SIZE][ARENA_PAGES - ARENA_AVAIL_PAGES];
33+
34+
SEC("syscall")
35+
__success __retval(0)
36+
int check_reserve3(void *ctx)
37+
{
38+
#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
39+
void __arena *guard, *globals;
40+
int ret;
41+
42+
guard = (void __arena *)arena_base(&arena);
43+
globals = (void __arena *)(arena_base(&arena) + 4 * PAGE_SIZE);
44+
45+
/*
46+
* The data should be offset 4 pages in (the largest
47+
* possible power of 2 that still leaves enough room
48+
* to the global data).
49+
*/
50+
ret = bpf_arena_reserve_pages(&arena, guard, 4);
51+
if (ret)
52+
return 1;
53+
54+
ret = bpf_arena_reserve_pages(&arena, globals, 1);
55+
if (!ret)
56+
return 2;
57+
#endif
58+
return 0;
59+
}
60+
61+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)