FILE
stream.c
File preview with syntax highlighting.
linux-6.19.14/tools/testing/selftests/bpf/progs/stream.c
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */ 3#include <vmlinux.h> 4#include <bpf/bpf_tracing.h> 5#include <bpf/bpf_helpers.h> 6#include "bpf_misc.h" 7#include "bpf_experimental.h" 8#include "bpf_arena_common.h" 9 10struct arr_elem { 11 struct bpf_res_spin_lock lock; 12}; 13 14struct { 15 __uint(type, BPF_MAP_TYPE_ARRAY); 16 __uint(max_entries, 1); 17 __type(key, int); 18 __type(value, struct arr_elem); 19} arrmap SEC(".maps"); 20 21struct { 22 __uint(type, BPF_MAP_TYPE_ARENA); 23 __uint(map_flags, BPF_F_MMAPABLE); 24 __uint(max_entries, 1); /* number of pages */ 25} arena SEC(".maps"); 26 27struct elem { 28 struct bpf_timer timer; 29}; 30 31struct { 32 __uint(type, BPF_MAP_TYPE_ARRAY); 33 __uint(max_entries, 1); 34 __type(key, int); 35 __type(value, struct elem); 36} array SEC(".maps"); 37 38#define ENOSPC 28 39#define _STR "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 40 41int size; 42u64 fault_addr; 43void *arena_ptr; 44 45SEC("syscall") 46__success __retval(0) 47int stream_exhaust(void *ctx) 48{ 49 /* Use global variable for loop convergence. */ 50 size = 0; 51 bpf_repeat(BPF_MAX_LOOPS) { 52 if (bpf_stream_printk(BPF_STDOUT, _STR) == -ENOSPC && size == 99954) 53 return 0; 54 size += sizeof(_STR) - 1; 55 } 56 return 1; 57} 58 59SEC("syscall") 60__arch_x86_64 61__arch_arm64 62__arch_s390x 63__success __retval(0) 64__stderr("ERROR: Timeout detected for may_goto instruction") 65__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 66__stderr("Call trace:\n" 67"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 68"|[ \t]+[^\n]+\n)*}}") 69int stream_cond_break(void *ctx) 70{ 71 while (can_loop) 72 ; 73 return 0; 74} 75 76SEC("syscall") 77__success __retval(0) 78__stderr("ERROR: AA or ABBA deadlock detected for bpf_res_spin_lock") 79__stderr("{{Attempted lock = (0x[0-9a-fA-F]+)\n" 80"Total held locks = 1\n" 81"Held lock\\[ 0\\] = \\1}}") 82__stderr("...") 83__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 84__stderr("Call trace:\n" 85"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 86"|[ \t]+[^\n]+\n)*}}") 87int stream_deadlock(void *ctx) 88{ 89 struct bpf_res_spin_lock *lock, *nlock; 90 91 lock = bpf_map_lookup_elem(&arrmap, &(int){0}); 92 if (!lock) 93 return 1; 94 nlock = bpf_map_lookup_elem(&arrmap, &(int){0}); 95 if (!nlock) 96 return 1; 97 if (bpf_res_spin_lock(lock)) 98 return 1; 99 if (bpf_res_spin_lock(nlock)) { 100 bpf_res_spin_unlock(lock); 101 return 0; 102 } 103 bpf_res_spin_unlock(nlock); 104 bpf_res_spin_unlock(lock); 105 return 1; 106} 107 108SEC("syscall") 109__success __retval(0) 110int stream_syscall(void *ctx) 111{ 112 bpf_stream_printk(BPF_STDOUT, "foo"); 113 return 0; 114} 115 116SEC("syscall") 117__arch_x86_64 118__arch_arm64 119__success __retval(0) 120__stderr("ERROR: Arena WRITE access at unmapped address 0x{{.*}}") 121__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 122__stderr("Call trace:\n" 123"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 124"|[ \t]+[^\n]+\n)*}}") 125int stream_arena_write_fault(void *ctx) 126{ 127 struct bpf_arena *ptr = (void *)&arena; 128 u64 user_vm_start; 129 130 /* Prevent GCC bounds warning: casting &arena to struct bpf_arena * 131 * triggers bounds checking since the map definition is smaller than struct 132 * bpf_arena. barrier_var() makes the pointer opaque to GCC, preventing the 133 * bounds analysis 134 */ 135 barrier_var(ptr); 136 user_vm_start = ptr->user_vm_start; 137 fault_addr = user_vm_start + 0x7fff; 138 bpf_addr_space_cast(user_vm_start, 0, 1); 139 asm volatile ( 140 "r1 = %0;" 141 "r2 = 1;" 142 "*(u32 *)(r1 + 0x7fff) = r2;" 143 : 144 : "r" (user_vm_start) 145 : "r1", "r2" 146 ); 147 return 0; 148} 149 150SEC("syscall") 151__arch_x86_64 152__arch_arm64 153__success __retval(0) 154__stderr("ERROR: Arena READ access at unmapped address 0x{{.*}}") 155__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 156__stderr("Call trace:\n" 157"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 158"|[ \t]+[^\n]+\n)*}}") 159int stream_arena_read_fault(void *ctx) 160{ 161 struct bpf_arena *ptr = (void *)&arena; 162 u64 user_vm_start; 163 164 /* Prevent GCC bounds warning: casting &arena to struct bpf_arena * 165 * triggers bounds checking since the map definition is smaller than struct 166 * bpf_arena. barrier_var() makes the pointer opaque to GCC, preventing the 167 * bounds analysis 168 */ 169 barrier_var(ptr); 170 user_vm_start = ptr->user_vm_start; 171 fault_addr = user_vm_start + 0x7fff; 172 bpf_addr_space_cast(user_vm_start, 0, 1); 173 asm volatile ( 174 "r1 = %0;" 175 "r1 = *(u32 *)(r1 + 0x7fff);" 176 : 177 : "r" (user_vm_start) 178 : "r1" 179 ); 180 return 0; 181} 182 183static __noinline void subprog(void) 184{ 185 int __arena *addr = (int __arena *)0xdeadbeef; 186 187 arena_ptr = &arena; 188 *addr = 1; 189} 190 191SEC("syscall") 192__arch_x86_64 193__arch_arm64 194__success __retval(0) 195__stderr("ERROR: Arena WRITE access at unmapped address 0x{{.*}}") 196__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 197__stderr("Call trace:\n" 198"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 199"|[ \t]+[^\n]+\n)*}}") 200int stream_arena_subprog_fault(void *ctx) 201{ 202 subprog(); 203 return 0; 204} 205 206static __noinline int timer_cb(void *map, int *key, struct bpf_timer *timer) 207{ 208 int __arena *addr = (int __arena *)0xdeadbeef; 209 210 arena_ptr = &arena; 211 *addr = 1; 212 return 0; 213} 214 215SEC("syscall") 216__arch_x86_64 217__arch_arm64 218__success __retval(0) 219__stderr("ERROR: Arena WRITE access at unmapped address 0x{{.*}}") 220__stderr("CPU: {{[0-9]+}} UID: 0 PID: {{[0-9]+}} Comm: {{.*}}") 221__stderr("Call trace:\n" 222"{{([a-zA-Z_][a-zA-Z0-9_]*\\+0x[0-9a-fA-F]+/0x[0-9a-fA-F]+\n" 223"|[ \t]+[^\n]+\n)*}}") 224int stream_arena_callback_fault(void *ctx) 225{ 226 struct bpf_timer *arr_timer; 227 228 arr_timer = bpf_map_lookup_elem(&array, &(int){0}); 229 if (!arr_timer) 230 return 0; 231 bpf_timer_init(arr_timer, &array, 1); 232 bpf_timer_set_callback(arr_timer, timer_cb); 233 bpf_timer_start(arr_timer, 0, 0); 234 return 0; 235} 236 237char _license[] SEC("license") = "GPL";
~/
Read-only file preview.