xref: /linux/tools/testing/selftests/bpf/progs/verifier_arena.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
180a4129fSAlexei Starovoitov // SPDX-License-Identifier: GPL-2.0
280a4129fSAlexei Starovoitov /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
380a4129fSAlexei Starovoitov 
4*6a826014SDaniel Xu #define BPF_NO_KFUNC_PROTOTYPES
580a4129fSAlexei Starovoitov #include <vmlinux.h>
680a4129fSAlexei Starovoitov #include <bpf/bpf_helpers.h>
780a4129fSAlexei Starovoitov #include <bpf/bpf_tracing.h>
880a4129fSAlexei Starovoitov #include "bpf_misc.h"
980a4129fSAlexei Starovoitov #include "bpf_experimental.h"
1080a4129fSAlexei Starovoitov #include "bpf_arena_common.h"
1180a4129fSAlexei Starovoitov 
1280a4129fSAlexei Starovoitov struct {
1380a4129fSAlexei Starovoitov 	__uint(type, BPF_MAP_TYPE_ARENA);
1480a4129fSAlexei Starovoitov 	__uint(map_flags, BPF_F_MMAPABLE);
1580a4129fSAlexei Starovoitov 	__uint(max_entries, 2); /* arena of two pages close to 32-bit boundary*/
16fa3550dcSPuranjay Mohan #ifdef __TARGET_ARCH_arm64
17fa3550dcSPuranjay Mohan         __ulong(map_extra, (1ull << 32) | (~0u - __PAGE_SIZE * 2 + 1)); /* start of mmap() region */
18fa3550dcSPuranjay Mohan #else
1980a4129fSAlexei Starovoitov         __ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * 2 + 1)); /* start of mmap() region */
20fa3550dcSPuranjay Mohan #endif
2180a4129fSAlexei Starovoitov } arena SEC(".maps");
2280a4129fSAlexei Starovoitov 
2380a4129fSAlexei Starovoitov SEC("syscall")
2480a4129fSAlexei Starovoitov __success __retval(0)
basic_alloc1(void * ctx)2580a4129fSAlexei Starovoitov int basic_alloc1(void *ctx)
2680a4129fSAlexei Starovoitov {
2710ebe835SAlexei Starovoitov #if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
2880a4129fSAlexei Starovoitov 	volatile int __arena *page1, *page2, *no_page, *page3;
2980a4129fSAlexei Starovoitov 
3080a4129fSAlexei Starovoitov 	page1 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
3180a4129fSAlexei Starovoitov 	if (!page1)
3280a4129fSAlexei Starovoitov 		return 1;
3380a4129fSAlexei Starovoitov 	*page1 = 1;
3480a4129fSAlexei Starovoitov 	page2 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
3580a4129fSAlexei Starovoitov 	if (!page2)
3680a4129fSAlexei Starovoitov 		return 2;
3780a4129fSAlexei Starovoitov 	*page2 = 2;
3880a4129fSAlexei Starovoitov 	no_page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
3980a4129fSAlexei Starovoitov 	if (no_page)
4080a4129fSAlexei Starovoitov 		return 3;
4180a4129fSAlexei Starovoitov 	if (*page1 != 1)
4280a4129fSAlexei Starovoitov 		return 4;
4380a4129fSAlexei Starovoitov 	if (*page2 != 2)
4480a4129fSAlexei Starovoitov 		return 5;
4580a4129fSAlexei Starovoitov 	bpf_arena_free_pages(&arena, (void __arena *)page2, 1);
4680a4129fSAlexei Starovoitov 	if (*page1 != 1)
4780a4129fSAlexei Starovoitov 		return 6;
4880a4129fSAlexei Starovoitov 	if (*page2 != 0) /* use-after-free should return 0 */
4980a4129fSAlexei Starovoitov 		return 7;
5080a4129fSAlexei Starovoitov 	page3 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
5180a4129fSAlexei Starovoitov 	if (!page3)
5280a4129fSAlexei Starovoitov 		return 8;
5380a4129fSAlexei Starovoitov 	*page3 = 3;
5480a4129fSAlexei Starovoitov 	if (page2 != page3)
5580a4129fSAlexei Starovoitov 		return 9;
5680a4129fSAlexei Starovoitov 	if (*page1 != 1)
5780a4129fSAlexei Starovoitov 		return 10;
5880a4129fSAlexei Starovoitov #endif
5980a4129fSAlexei Starovoitov 	return 0;
6080a4129fSAlexei Starovoitov }
6180a4129fSAlexei Starovoitov 
6280a4129fSAlexei Starovoitov SEC("syscall")
6380a4129fSAlexei Starovoitov __success __retval(0)
basic_alloc2(void * ctx)6480a4129fSAlexei Starovoitov int basic_alloc2(void *ctx)
6580a4129fSAlexei Starovoitov {
6610ebe835SAlexei Starovoitov #if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
6780a4129fSAlexei Starovoitov 	volatile char __arena *page1, *page2, *page3, *page4;
6880a4129fSAlexei Starovoitov 
6980a4129fSAlexei Starovoitov 	page1 = bpf_arena_alloc_pages(&arena, NULL, 2, NUMA_NO_NODE, 0);
7080a4129fSAlexei Starovoitov 	if (!page1)
7180a4129fSAlexei Starovoitov 		return 1;
7280a4129fSAlexei Starovoitov 	page2 = page1 + __PAGE_SIZE;
7380a4129fSAlexei Starovoitov 	page3 = page1 + __PAGE_SIZE * 2;
7480a4129fSAlexei Starovoitov 	page4 = page1 - __PAGE_SIZE;
7580a4129fSAlexei Starovoitov 	*page1 = 1;
7680a4129fSAlexei Starovoitov 	*page2 = 2;
7780a4129fSAlexei Starovoitov 	*page3 = 3;
7880a4129fSAlexei Starovoitov 	*page4 = 4;
7980a4129fSAlexei Starovoitov 	if (*page1 != 1)
8080a4129fSAlexei Starovoitov 		return 1;
8180a4129fSAlexei Starovoitov 	if (*page2 != 2)
8280a4129fSAlexei Starovoitov 		return 2;
8380a4129fSAlexei Starovoitov 	if (*page3 != 0)
8480a4129fSAlexei Starovoitov 		return 3;
8580a4129fSAlexei Starovoitov 	if (*page4 != 0)
8680a4129fSAlexei Starovoitov 		return 4;
8780a4129fSAlexei Starovoitov 	bpf_arena_free_pages(&arena, (void __arena *)page1, 2);
8880a4129fSAlexei Starovoitov 	if (*page1 != 0)
8980a4129fSAlexei Starovoitov 		return 5;
9080a4129fSAlexei Starovoitov 	if (*page2 != 0)
9180a4129fSAlexei Starovoitov 		return 6;
9280a4129fSAlexei Starovoitov 	if (*page3 != 0)
9380a4129fSAlexei Starovoitov 		return 7;
9480a4129fSAlexei Starovoitov 	if (*page4 != 0)
9580a4129fSAlexei Starovoitov 		return 8;
9680a4129fSAlexei Starovoitov #endif
9780a4129fSAlexei Starovoitov 	return 0;
9880a4129fSAlexei Starovoitov }
9980a4129fSAlexei Starovoitov 
10080a4129fSAlexei Starovoitov struct bpf_arena___l {
10180a4129fSAlexei Starovoitov         struct bpf_map map;
10280a4129fSAlexei Starovoitov } __attribute__((preserve_access_index));
10380a4129fSAlexei Starovoitov 
10480a4129fSAlexei Starovoitov SEC("syscall")
10580a4129fSAlexei Starovoitov __success __retval(0) __log_level(2)
basic_alloc3(void * ctx)10680a4129fSAlexei Starovoitov int basic_alloc3(void *ctx)
10780a4129fSAlexei Starovoitov {
10880a4129fSAlexei Starovoitov 	struct bpf_arena___l *ar = (struct bpf_arena___l *)&arena;
10980a4129fSAlexei Starovoitov 	volatile char __arena *pages;
11080a4129fSAlexei Starovoitov 
11180a4129fSAlexei Starovoitov 	pages = bpf_arena_alloc_pages(&ar->map, NULL, ar->map.max_entries, NUMA_NO_NODE, 0);
11280a4129fSAlexei Starovoitov 	if (!pages)
11380a4129fSAlexei Starovoitov 		return 1;
11480a4129fSAlexei Starovoitov 	return 0;
11580a4129fSAlexei Starovoitov }
11680a4129fSAlexei Starovoitov 
11780a4129fSAlexei Starovoitov SEC("iter.s/bpf_map")
11880a4129fSAlexei Starovoitov __success __log_level(2)
iter_maps1(struct bpf_iter__bpf_map * ctx)11980a4129fSAlexei Starovoitov int iter_maps1(struct bpf_iter__bpf_map *ctx)
12080a4129fSAlexei Starovoitov {
12180a4129fSAlexei Starovoitov 	struct bpf_map *map = ctx->map;
12280a4129fSAlexei Starovoitov 
12380a4129fSAlexei Starovoitov 	if (!map)
12480a4129fSAlexei Starovoitov 		return 0;
12580a4129fSAlexei Starovoitov 	bpf_arena_alloc_pages(map, NULL, map->max_entries, 0, 0);
12680a4129fSAlexei Starovoitov 	return 0;
12780a4129fSAlexei Starovoitov }
12880a4129fSAlexei Starovoitov 
12980a4129fSAlexei Starovoitov SEC("iter.s/bpf_map")
13080a4129fSAlexei Starovoitov __failure __msg("expected pointer to STRUCT bpf_map")
iter_maps2(struct bpf_iter__bpf_map * ctx)13180a4129fSAlexei Starovoitov int iter_maps2(struct bpf_iter__bpf_map *ctx)
13280a4129fSAlexei Starovoitov {
13380a4129fSAlexei Starovoitov 	struct seq_file *seq = ctx->meta->seq;
13480a4129fSAlexei Starovoitov 
13580a4129fSAlexei Starovoitov 	bpf_arena_alloc_pages((void *)seq, NULL, 1, 0, 0);
13680a4129fSAlexei Starovoitov 	return 0;
13780a4129fSAlexei Starovoitov }
13880a4129fSAlexei Starovoitov 
13980a4129fSAlexei Starovoitov SEC("iter.s/bpf_map")
14080a4129fSAlexei Starovoitov __failure __msg("untrusted_ptr_bpf_map")
iter_maps3(struct bpf_iter__bpf_map * ctx)14180a4129fSAlexei Starovoitov int iter_maps3(struct bpf_iter__bpf_map *ctx)
14280a4129fSAlexei Starovoitov {
14380a4129fSAlexei Starovoitov 	struct bpf_map *map = ctx->map;
14480a4129fSAlexei Starovoitov 
14580a4129fSAlexei Starovoitov 	if (!map)
14680a4129fSAlexei Starovoitov 		return 0;
14780a4129fSAlexei Starovoitov 	bpf_arena_alloc_pages(map->inner_map_meta, NULL, map->max_entries, 0, 0);
14880a4129fSAlexei Starovoitov 	return 0;
14980a4129fSAlexei Starovoitov }
15080a4129fSAlexei Starovoitov 
15180a4129fSAlexei Starovoitov char _license[] SEC("license") = "GPL";
152