@@ -139,4 +139,122 @@ __naked void on_the_inner_map_pointer(void)
139
139
: __clobber_all );
140
140
}
141
141
142
+ SEC ("socket" )
143
+ __description ("map_ptr is never null" )
144
+ __success
145
+ __naked void map_ptr_is_never_null (void )
146
+ {
147
+ asm volatile (" \
148
+ r0 = 0; \
149
+ r1 = %[map_in_map] ll; \
150
+ if r1 != 0 goto l0_%=; \
151
+ r10 = 42; \
152
+ l0_%=: exit; \
153
+ " :
154
+ : __imm (bpf_map_lookup_elem ),
155
+ __imm_addr (map_in_map )
156
+ : __clobber_all );
157
+ }
158
+
159
+ SEC ("socket" )
160
+ __description ("map_ptr is never null inner" )
161
+ __success
162
+ __naked void map_ptr_is_never_null_inner (void )
163
+ {
164
+ asm volatile (" \
165
+ r1 = 0; \
166
+ *(u32*)(r10 - 4) = r1; \
167
+ r2 = r10; \
168
+ r2 += -4; \
169
+ r1 = %[map_in_map] ll; \
170
+ call %[bpf_map_lookup_elem]; \
171
+ if r0 == 0 goto l0_%=; \
172
+ if r0 != 0 goto l0_%=; \
173
+ r10 = 42; \
174
+ l0_%=: exit; \
175
+ " :
176
+ : __imm (bpf_map_lookup_elem ),
177
+ __imm_addr (map_in_map )
178
+ : __clobber_all );
179
+ }
180
+
181
+ SEC ("socket" )
182
+ __description ("map_ptr is never null inner spill fill" )
183
+ __success
184
+ __naked void map_ptr_is_never_null_inner_spill_fill (void )
185
+ {
186
+ asm volatile (" \
187
+ r1 = 0; \
188
+ *(u32*)(r10 - 4) = r1; \
189
+ r2 = r10; \
190
+ r2 += -4; \
191
+ r1 = %[map_in_map] ll; \
192
+ call %[bpf_map_lookup_elem]; \
193
+ if r0 != 0 goto l0_%=; \
194
+ exit; \
195
+ l0_%=: *(u64 *)(r10 -16) = r0; \
196
+ r1 = *(u64 *)(r10 -16); \
197
+ if r1 == 0 goto l1_%=; \
198
+ exit; \
199
+ l1_%=: r10 = 42; \
200
+ exit; \
201
+ " :
202
+ : __imm (bpf_map_lookup_elem ),
203
+ __imm_addr (map_in_map )
204
+ : __clobber_all );
205
+ }
206
+
207
+ struct {
208
+ __uint (type , BPF_MAP_TYPE_ARRAY_OF_MAPS );
209
+ __uint (max_entries , 1 );
210
+ __type (key , int );
211
+ __type (value , int );
212
+ __array (values , struct {
213
+ __uint (type , BPF_MAP_TYPE_RINGBUF );
214
+ __uint (max_entries , 64 * 1024 );
215
+ });
216
+ } rb_in_map SEC (".maps" );
217
+
218
+ struct rb_ctx {
219
+ void * rb ;
220
+ struct bpf_dynptr dptr ;
221
+ };
222
+
223
+ static __always_inline struct rb_ctx __rb_event_reserve (__u32 sz )
224
+ {
225
+ struct rb_ctx rb_ctx = {};
226
+ void * rb ;
227
+ __u32 cpu = bpf_get_smp_processor_id ();
228
+ __u32 rb_slot = cpu & 1 ;
229
+
230
+ rb = bpf_map_lookup_elem (& rb_in_map , & rb_slot );
231
+ if (!rb )
232
+ return rb_ctx ;
233
+
234
+ rb_ctx .rb = rb ;
235
+ bpf_ringbuf_reserve_dynptr (rb , sz , 0 , & rb_ctx .dptr );
236
+
237
+ return rb_ctx ;
238
+ }
239
+
240
+ static __noinline void __rb_event_submit (struct rb_ctx * ctx )
241
+ {
242
+ if (!ctx -> rb )
243
+ return ;
244
+
245
+ /* If the verifier (incorrectly) concludes that ctx->rb can be
246
+ * NULL at this point, we'll get "BPF_EXIT instruction in main
247
+ * prog would lead to reference leak" error
248
+ */
249
+ bpf_ringbuf_submit_dynptr (& ctx -> dptr , 0 );
250
+ }
251
+
252
+ SEC ("socket" )
253
+ int map_ptr_is_never_null_rb (void * ctx )
254
+ {
255
+ struct rb_ctx event_ctx = __rb_event_reserve (256 );
256
+ __rb_event_submit (& event_ctx );
257
+ return 0 ;
258
+ }
259
+
142
260
char _license [] SEC ("license" ) = "GPL" ;
0 commit comments