55#include <bpf/bpf_helpers.h>
66#include "bpf_misc.h"
77#include "bpf_experimental.h"
8+ #include "bpf_arena_common.h"
89
910struct arr_elem {
1011 struct bpf_res_spin_lock lock ;
@@ -17,10 +18,29 @@ struct {
1718 __type (value , struct arr_elem );
1819} arrmap SEC (".maps" );
1920
21+ struct {
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+
27+ struct elem {
28+ struct bpf_timer timer ;
29+ };
30+
31+ struct {
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+
2038#define ENOSPC 28
2139#define _STR "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
2240
2341int size ;
42+ u64 fault_addr ;
43+ void * arena_ptr ;
2444
2545SEC ("syscall" )
2646__success __retval (0 )
@@ -93,4 +113,125 @@ int stream_syscall(void *ctx)
93113 return 0 ;
94114}
95115
116+ SEC ("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)*}}" )
125+ int 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+
150+ SEC ("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)*}}" )
159+ int 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+
183+ static __noinline void subprog (void )
184+ {
185+ int __arena * addr = (int __arena * )0xdeadbeef ;
186+
187+ arena_ptr = & arena ;
188+ * addr = 1 ;
189+ }
190+
191+ SEC ("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)*}}" )
200+ int stream_arena_subprog_fault (void * ctx )
201+ {
202+ subprog ();
203+ return 0 ;
204+ }
205+
206+ static __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+
215+ SEC ("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)*}}" )
224+ int 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+
96237char _license [] SEC ("license" ) = "GPL" ;
0 commit comments