File Index
Files and directories
Sign in
FILE

verifier_arena.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/verifier_arena.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
  3
  4#define BPF_NO_KFUNC_PROTOTYPES
  5#include <vmlinux.h>
  6#include <errno.h>
  7#include <bpf/bpf_helpers.h>
  8#include <bpf/bpf_tracing.h>
  9#include "bpf_misc.h"
 10#include "bpf_experimental.h"
 11#include "bpf_arena_common.h"
 12
 13struct {
 14	__uint(type, BPF_MAP_TYPE_ARENA);
 15	__uint(map_flags, BPF_F_MMAPABLE);
 16	__uint(max_entries, 2); /* arena of two pages close to 32-bit boundary*/
 17#ifdef __TARGET_ARCH_arm64
 18        __ulong(map_extra, (1ull << 32) | (~0u - __PAGE_SIZE * 2 + 1)); /* start of mmap() region */
 19#else
 20        __ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * 2 + 1)); /* start of mmap() region */
 21#endif
 22} arena SEC(".maps");
 23
 24SEC("syscall")
 25__success __retval(0)
 26int basic_alloc1(void *ctx)
 27{
 28#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 29	volatile int __arena *page1, *page2, *no_page, *page3;
 30
 31	page1 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
 32	if (!page1)
 33		return 1;
 34	*page1 = 1;
 35	page2 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
 36	if (!page2)
 37		return 2;
 38	*page2 = 2;
 39	no_page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
 40	if (no_page)
 41		return 3;
 42	if (*page1 != 1)
 43		return 4;
 44	if (*page2 != 2)
 45		return 5;
 46	bpf_arena_free_pages(&arena, (void __arena *)page2, 1);
 47	if (*page1 != 1)
 48		return 6;
 49	if (*page2 != 0) /* use-after-free should return 0 */
 50		return 7;
 51	page3 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
 52	if (!page3)
 53		return 8;
 54	*page3 = 3;
 55	if (page2 != page3)
 56		return 9;
 57	if (*page1 != 1)
 58		return 10;
 59#endif
 60	return 0;
 61}
 62
 63SEC("syscall")
 64__success __retval(0)
 65int basic_alloc2(void *ctx)
 66{
 67#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 68	volatile char __arena *page1, *page2, *page3, *page4;
 69
 70	page1 = bpf_arena_alloc_pages(&arena, NULL, 2, NUMA_NO_NODE, 0);
 71	if (!page1)
 72		return 1;
 73	page2 = page1 + __PAGE_SIZE;
 74	page3 = page1 + __PAGE_SIZE * 2;
 75	page4 = page1 - __PAGE_SIZE;
 76	*page1 = 1;
 77	*page2 = 2;
 78	*page3 = 3;
 79	*page4 = 4;
 80	if (*page1 != 1)
 81		return 1;
 82	if (*page2 != 2)
 83		return 2;
 84	if (*page3 != 0)
 85		return 3;
 86	if (*page4 != 0)
 87		return 4;
 88	bpf_arena_free_pages(&arena, (void __arena *)page1, 2);
 89	if (*page1 != 0)
 90		return 5;
 91	if (*page2 != 0)
 92		return 6;
 93	if (*page3 != 0)
 94		return 7;
 95	if (*page4 != 0)
 96		return 8;
 97#endif
 98	return 0;
 99}
100
101struct bpf_arena___l {
102        struct bpf_map map;
103} __attribute__((preserve_access_index));
104
105SEC("syscall")
106__success __retval(0) __log_level(2)
107int basic_alloc3(void *ctx)
108{
109	struct bpf_arena___l *ar = (struct bpf_arena___l *)&arena;
110	volatile char __arena *pages;
111
112	pages = bpf_arena_alloc_pages(&ar->map, NULL, ar->map.max_entries, NUMA_NO_NODE, 0);
113	if (!pages)
114		return 1;
115	return 0;
116}
117
118SEC("syscall")
119__success __retval(0)
120int basic_reserve1(void *ctx)
121{
122#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
123	char __arena *page;
124	int ret;
125
126	page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
127	if (!page)
128		return 1;
129
130	page += __PAGE_SIZE;
131
132	/* Reserve the second page */
133	ret = bpf_arena_reserve_pages(&arena, page, 1);
134	if (ret)
135		return 2;
136
137	/* Try to explicitly allocate the reserved page. */
138	page = bpf_arena_alloc_pages(&arena, page, 1, NUMA_NO_NODE, 0);
139	if (page)
140		return 3;
141
142	/* Try to implicitly allocate the page (since there's only 2 of them). */
143	page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
144	if (page)
145		return 4;
146#endif
147	return 0;
148}
149
150SEC("syscall")
151__success __retval(0)
152int basic_reserve2(void *ctx)
153{
154#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
155	char __arena *page;
156	int ret;
157
158	page = arena_base(&arena);
159	ret = bpf_arena_reserve_pages(&arena, page, 1);
160	if (ret)
161		return 1;
162
163	page = bpf_arena_alloc_pages(&arena, page, 1, NUMA_NO_NODE, 0);
164	if ((u64)page)
165		return 2;
166#endif
167	return 0;
168}
169
170/* Reserve the same page twice, should return -EBUSY. */
171SEC("syscall")
172__success __retval(0)
173int reserve_twice(void *ctx)
174{
175#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
176	char __arena *page;
177	int ret;
178
179	page = arena_base(&arena);
180
181	ret = bpf_arena_reserve_pages(&arena, page, 1);
182	if (ret)
183		return 1;
184
185	ret = bpf_arena_reserve_pages(&arena, page, 1);
186	if (ret != -EBUSY)
187		return 2;
188#endif
189	return 0;
190}
191
192/* Try to reserve past the end of the arena. */
193SEC("syscall")
194__success __retval(0)
195int reserve_invalid_region(void *ctx)
196{
197#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
198	char __arena *page;
199	int ret;
200
201	/* Try a NULL pointer. */
202	ret = bpf_arena_reserve_pages(&arena, NULL, 3);
203	if (ret != -EINVAL)
204		return 1;
205
206	page = arena_base(&arena);
207
208	ret = bpf_arena_reserve_pages(&arena, page, 3);
209	if (ret != -EINVAL)
210		return 2;
211
212	ret = bpf_arena_reserve_pages(&arena, page, 4096);
213	if (ret != -EINVAL)
214		return 3;
215
216	ret = bpf_arena_reserve_pages(&arena, page, (1ULL << 32) - 1);
217	if (ret != -EINVAL)
218		return 4;
219#endif
220	return 0;
221}
222
223SEC("iter.s/bpf_map")
224__success __log_level(2)
225int iter_maps1(struct bpf_iter__bpf_map *ctx)
226{
227	struct bpf_map *map = ctx->map;
228
229	if (!map)
230		return 0;
231	bpf_arena_alloc_pages(map, NULL, map->max_entries, 0, 0);
232	return 0;
233}
234
235SEC("iter.s/bpf_map")
236__failure __msg("expected pointer to STRUCT bpf_map")
237int iter_maps2(struct bpf_iter__bpf_map *ctx)
238{
239	struct seq_file *seq = ctx->meta->seq;
240
241	bpf_arena_alloc_pages((void *)seq, NULL, 1, 0, 0);
242	return 0;
243}
244
245SEC("iter.s/bpf_map")
246__failure __msg("untrusted_ptr_bpf_map")
247int iter_maps3(struct bpf_iter__bpf_map *ctx)
248{
249	struct bpf_map *map = ctx->map;
250
251	if (!map)
252		return 0;
253	bpf_arena_alloc_pages(map->inner_map_meta, NULL, map->max_entries, 0, 0);
254	return 0;
255}
256
257char _license[] SEC("license") = "GPL";
~/ Read-only file preview.