1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 4 #include <vmlinux.h> 5 #include <bpf/bpf_helpers.h> 6 #include <bpf/bpf_tracing.h> 7 #include "bpf_misc.h" 8 #include "bpf_experimental.h" 9 #include "bpf_arena_common.h" 10 11 struct { 12 __uint(type, BPF_MAP_TYPE_ARENA); 13 __uint(map_flags, BPF_F_MMAPABLE); 14 __uint(max_entries, 2); /* arena of two pages close to 32-bit boundary*/ 15 __ulong(map_extra, (1ull << 44) | (~0u - __PAGE_SIZE * 2 + 1)); /* start of mmap() region */ 16 } arena SEC(".maps"); 17 18 SEC("syscall") 19 __success __retval(0) 20 int basic_alloc1(void *ctx) 21 { 22 #if defined(__BPF_FEATURE_ARENA_CAST) 23 volatile int __arena *page1, *page2, *no_page, *page3; 24 25 page1 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0); 26 if (!page1) 27 return 1; 28 *page1 = 1; 29 page2 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0); 30 if (!page2) 31 return 2; 32 *page2 = 2; 33 no_page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0); 34 if (no_page) 35 return 3; 36 if (*page1 != 1) 37 return 4; 38 if (*page2 != 2) 39 return 5; 40 bpf_arena_free_pages(&arena, (void __arena *)page2, 1); 41 if (*page1 != 1) 42 return 6; 43 if (*page2 != 0) /* use-after-free should return 0 */ 44 return 7; 45 page3 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0); 46 if (!page3) 47 return 8; 48 *page3 = 3; 49 if (page2 != page3) 50 return 9; 51 if (*page1 != 1) 52 return 10; 53 #endif 54 return 0; 55 } 56 57 SEC("syscall") 58 __success __retval(0) 59 int basic_alloc2(void *ctx) 60 { 61 #if defined(__BPF_FEATURE_ARENA_CAST) 62 volatile char __arena *page1, *page2, *page3, *page4; 63 64 page1 = bpf_arena_alloc_pages(&arena, NULL, 2, NUMA_NO_NODE, 0); 65 if (!page1) 66 return 1; 67 page2 = page1 + __PAGE_SIZE; 68 page3 = page1 + __PAGE_SIZE * 2; 69 page4 = page1 - __PAGE_SIZE; 70 *page1 = 1; 71 *page2 = 2; 72 *page3 = 3; 73 *page4 = 4; 74 if (*page1 != 1) 75 return 1; 76 if (*page2 != 2) 77 return 2; 78 if (*page3 != 0) 79 return 3; 80 if (*page4 != 0) 81 return 4; 82 bpf_arena_free_pages(&arena, (void __arena *)page1, 2); 83 if (*page1 != 0) 84 return 5; 85 if (*page2 != 0) 86 return 6; 87 if (*page3 != 0) 88 return 7; 89 if (*page4 != 0) 90 return 8; 91 #endif 92 return 0; 93 } 94 95 struct bpf_arena___l { 96 struct bpf_map map; 97 } __attribute__((preserve_access_index)); 98 99 SEC("syscall") 100 __success __retval(0) __log_level(2) 101 int basic_alloc3(void *ctx) 102 { 103 struct bpf_arena___l *ar = (struct bpf_arena___l *)&arena; 104 volatile char __arena *pages; 105 106 pages = bpf_arena_alloc_pages(&ar->map, NULL, ar->map.max_entries, NUMA_NO_NODE, 0); 107 if (!pages) 108 return 1; 109 return 0; 110 } 111 112 SEC("iter.s/bpf_map") 113 __success __log_level(2) 114 int iter_maps1(struct bpf_iter__bpf_map *ctx) 115 { 116 struct bpf_map *map = ctx->map; 117 118 if (!map) 119 return 0; 120 bpf_arena_alloc_pages(map, NULL, map->max_entries, 0, 0); 121 return 0; 122 } 123 124 SEC("iter.s/bpf_map") 125 __failure __msg("expected pointer to STRUCT bpf_map") 126 int iter_maps2(struct bpf_iter__bpf_map *ctx) 127 { 128 struct seq_file *seq = ctx->meta->seq; 129 130 bpf_arena_alloc_pages((void *)seq, NULL, 1, 0, 0); 131 return 0; 132 } 133 134 SEC("iter.s/bpf_map") 135 __failure __msg("untrusted_ptr_bpf_map") 136 int iter_maps3(struct bpf_iter__bpf_map *ctx) 137 { 138 struct bpf_map *map = ctx->map; 139 140 if (!map) 141 return 0; 142 bpf_arena_alloc_pages(map->inner_map_meta, NULL, map->max_entries, 0, 0); 143 return 0; 144 } 145 146 char _license[] SEC("license") = "GPL"; 147