1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 #include <linux/bpf.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_tracing.h> 6 #include <stdbool.h> 7 #include "bpf_arena_common.h" 8 9 struct { 10 __uint(type, BPF_MAP_TYPE_ARENA); 11 __uint(map_flags, BPF_F_MMAPABLE); 12 __uint(max_entries, 10); /* number of pages */ 13 #ifdef __TARGET_ARCH_arm64 14 __ulong(map_extra, 0x1ull << 32); /* start of mmap() region */ 15 #else 16 __ulong(map_extra, 0x1ull << 44); /* start of mmap() region */ 17 #endif 18 } arena SEC(".maps"); 19 20 #if defined(ENABLE_ATOMICS_TESTS) && defined(__BPF_FEATURE_ADDR_SPACE_CAST) 21 bool skip_tests __attribute((__section__(".data"))) = false; 22 #else 23 bool skip_tests = true; 24 #endif 25 26 __u32 pid = 0; 27 28 __u64 __arena_global add64_value = 1; 29 __u64 __arena_global add64_result = 0; 30 __u32 __arena_global add32_value = 1; 31 __u32 __arena_global add32_result = 0; 32 __u64 __arena_global add_stack_value_copy = 0; 33 __u64 __arena_global add_stack_result = 0; 34 __u64 __arena_global add_noreturn_value = 1; 35 36 SEC("raw_tp/sys_enter") 37 int add(const void *ctx) 38 { 39 if (pid != (bpf_get_current_pid_tgid() >> 32)) 40 return 0; 41 #ifdef ENABLE_ATOMICS_TESTS 42 __u64 add_stack_value = 1; 43 44 add64_result = __sync_fetch_and_add(&add64_value, 2); 45 add32_result = __sync_fetch_and_add(&add32_value, 2); 46 add_stack_result = __sync_fetch_and_add(&add_stack_value, 2); 47 add_stack_value_copy = add_stack_value; 48 __sync_fetch_and_add(&add_noreturn_value, 2); 49 #endif 50 51 return 0; 52 } 53 54 __s64 __arena_global sub64_value = 1; 55 __s64 __arena_global sub64_result = 0; 56 __s32 __arena_global sub32_value = 1; 57 __s32 __arena_global sub32_result = 0; 58 __s64 __arena_global sub_stack_value_copy = 0; 59 __s64 __arena_global sub_stack_result = 0; 60 __s64 __arena_global sub_noreturn_value = 1; 61 62 SEC("raw_tp/sys_enter") 63 int sub(const void *ctx) 64 { 65 if (pid != (bpf_get_current_pid_tgid() >> 32)) 66 return 0; 67 #ifdef ENABLE_ATOMICS_TESTS 68 __u64 sub_stack_value = 1; 69 70 sub64_result = __sync_fetch_and_sub(&sub64_value, 2); 71 sub32_result = __sync_fetch_and_sub(&sub32_value, 2); 72 sub_stack_result = __sync_fetch_and_sub(&sub_stack_value, 2); 73 sub_stack_value_copy = sub_stack_value; 74 __sync_fetch_and_sub(&sub_noreturn_value, 2); 75 #endif 76 77 return 0; 78 } 79 80 __u64 __arena_global and64_value = (0x110ull << 32); 81 __u32 __arena_global and32_value = 0x110; 82 83 SEC("raw_tp/sys_enter") 84 int and(const void *ctx) 85 { 86 if (pid != (bpf_get_current_pid_tgid() >> 32)) 87 return 0; 88 #ifdef ENABLE_ATOMICS_TESTS 89 90 __sync_fetch_and_and(&and64_value, 0x011ull << 32); 91 __sync_fetch_and_and(&and32_value, 0x011); 92 #endif 93 94 return 0; 95 } 96 97 __u32 __arena_global or32_value = 0x110; 98 __u64 __arena_global or64_value = (0x110ull << 32); 99 100 SEC("raw_tp/sys_enter") 101 int or(const void *ctx) 102 { 103 if (pid != (bpf_get_current_pid_tgid() >> 32)) 104 return 0; 105 #ifdef ENABLE_ATOMICS_TESTS 106 __sync_fetch_and_or(&or64_value, 0x011ull << 32); 107 __sync_fetch_and_or(&or32_value, 0x011); 108 #endif 109 110 return 0; 111 } 112 113 __u64 __arena_global xor64_value = (0x110ull << 32); 114 __u32 __arena_global xor32_value = 0x110; 115 116 SEC("raw_tp/sys_enter") 117 int xor(const void *ctx) 118 { 119 if (pid != (bpf_get_current_pid_tgid() >> 32)) 120 return 0; 121 #ifdef ENABLE_ATOMICS_TESTS 122 __sync_fetch_and_xor(&xor64_value, 0x011ull << 32); 123 __sync_fetch_and_xor(&xor32_value, 0x011); 124 #endif 125 126 return 0; 127 } 128 129 __u32 __arena_global cmpxchg32_value = 1; 130 __u32 __arena_global cmpxchg32_result_fail = 0; 131 __u32 __arena_global cmpxchg32_result_succeed = 0; 132 __u64 __arena_global cmpxchg64_value = 1; 133 __u64 __arena_global cmpxchg64_result_fail = 0; 134 __u64 __arena_global cmpxchg64_result_succeed = 0; 135 136 SEC("raw_tp/sys_enter") 137 int cmpxchg(const void *ctx) 138 { 139 if (pid != (bpf_get_current_pid_tgid() >> 32)) 140 return 0; 141 #ifdef ENABLE_ATOMICS_TESTS 142 cmpxchg64_result_fail = __sync_val_compare_and_swap(&cmpxchg64_value, 0, 3); 143 cmpxchg64_result_succeed = __sync_val_compare_and_swap(&cmpxchg64_value, 1, 2); 144 145 cmpxchg32_result_fail = __sync_val_compare_and_swap(&cmpxchg32_value, 0, 3); 146 cmpxchg32_result_succeed = __sync_val_compare_and_swap(&cmpxchg32_value, 1, 2); 147 #endif 148 149 return 0; 150 } 151 152 __u64 __arena_global xchg64_value = 1; 153 __u64 __arena_global xchg64_result = 0; 154 __u32 __arena_global xchg32_value = 1; 155 __u32 __arena_global xchg32_result = 0; 156 157 SEC("raw_tp/sys_enter") 158 int xchg(const void *ctx) 159 { 160 if (pid != (bpf_get_current_pid_tgid() >> 32)) 161 return 0; 162 #ifdef ENABLE_ATOMICS_TESTS 163 __u64 val64 = 2; 164 __u32 val32 = 2; 165 166 xchg64_result = __sync_lock_test_and_set(&xchg64_value, val64); 167 xchg32_result = __sync_lock_test_and_set(&xchg32_value, val32); 168 #endif 169 170 return 0; 171 } 172 173 __u64 __arena_global uaf_sink; 174 volatile __u64 __arena_global uaf_recovery_fails; 175 176 SEC("syscall") 177 int uaf(const void *ctx) 178 { 179 if (pid != (bpf_get_current_pid_tgid() >> 32)) 180 return 0; 181 #if defined(ENABLE_ATOMICS_TESTS) && !defined(__TARGET_ARCH_arm64) && \ 182 !defined(__TARGET_ARCH_x86) 183 __u32 __arena *page32; 184 __u64 __arena *page64; 185 void __arena *page; 186 187 page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0); 188 bpf_arena_free_pages(&arena, page, 1); 189 uaf_recovery_fails = 24; 190 191 page32 = (__u32 __arena *)page; 192 uaf_sink += __sync_fetch_and_add(page32, 1); 193 uaf_recovery_fails -= 1; 194 __sync_add_and_fetch(page32, 1); 195 uaf_recovery_fails -= 1; 196 uaf_sink += __sync_fetch_and_sub(page32, 1); 197 uaf_recovery_fails -= 1; 198 __sync_sub_and_fetch(page32, 1); 199 uaf_recovery_fails -= 1; 200 uaf_sink += __sync_fetch_and_and(page32, 1); 201 uaf_recovery_fails -= 1; 202 __sync_and_and_fetch(page32, 1); 203 uaf_recovery_fails -= 1; 204 uaf_sink += __sync_fetch_and_or(page32, 1); 205 uaf_recovery_fails -= 1; 206 __sync_or_and_fetch(page32, 1); 207 uaf_recovery_fails -= 1; 208 uaf_sink += __sync_fetch_and_xor(page32, 1); 209 uaf_recovery_fails -= 1; 210 __sync_xor_and_fetch(page32, 1); 211 uaf_recovery_fails -= 1; 212 uaf_sink += __sync_val_compare_and_swap(page32, 0, 1); 213 uaf_recovery_fails -= 1; 214 uaf_sink += __sync_lock_test_and_set(page32, 1); 215 uaf_recovery_fails -= 1; 216 217 page64 = (__u64 __arena *)page; 218 uaf_sink += __sync_fetch_and_add(page64, 1); 219 uaf_recovery_fails -= 1; 220 __sync_add_and_fetch(page64, 1); 221 uaf_recovery_fails -= 1; 222 uaf_sink += __sync_fetch_and_sub(page64, 1); 223 uaf_recovery_fails -= 1; 224 __sync_sub_and_fetch(page64, 1); 225 uaf_recovery_fails -= 1; 226 uaf_sink += __sync_fetch_and_and(page64, 1); 227 uaf_recovery_fails -= 1; 228 __sync_and_and_fetch(page64, 1); 229 uaf_recovery_fails -= 1; 230 uaf_sink += __sync_fetch_and_or(page64, 1); 231 uaf_recovery_fails -= 1; 232 __sync_or_and_fetch(page64, 1); 233 uaf_recovery_fails -= 1; 234 uaf_sink += __sync_fetch_and_xor(page64, 1); 235 uaf_recovery_fails -= 1; 236 __sync_xor_and_fetch(page64, 1); 237 uaf_recovery_fails -= 1; 238 uaf_sink += __sync_val_compare_and_swap(page64, 0, 1); 239 uaf_recovery_fails -= 1; 240 uaf_sink += __sync_lock_test_and_set(page64, 1); 241 uaf_recovery_fails -= 1; 242 #endif 243 244 return 0; 245 } 246 247 char _license[] SEC("license") = "GPL"; 248