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