File Index
Files and directories
Sign in
FILE

stream.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/stream.c 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.