xref: /linux/tools/testing/selftests/bpf/progs/verifier_sock.c (revision 5256161e3573e0e35ac5e12f8ca904cf51e77f5b)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/sock.c */
3 
4 #include "vmlinux.h"
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7 
8 struct {
9 	__uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
10 	__uint(max_entries, 1);
11 	__type(key, __u32);
12 	__type(value, __u64);
13 } map_reuseport_array SEC(".maps");
14 
15 struct {
16 	__uint(type, BPF_MAP_TYPE_SOCKHASH);
17 	__uint(max_entries, 1);
18 	__type(key, int);
19 	__type(value, int);
20 } map_sockhash SEC(".maps");
21 
22 struct {
23 	__uint(type, BPF_MAP_TYPE_SOCKMAP);
24 	__uint(max_entries, 1);
25 	__type(key, int);
26 	__type(value, int);
27 } map_sockmap SEC(".maps");
28 
29 struct {
30 	__uint(type, BPF_MAP_TYPE_XSKMAP);
31 	__uint(max_entries, 1);
32 	__type(key, int);
33 	__type(value, int);
34 } map_xskmap SEC(".maps");
35 
36 struct val {
37 	int cnt;
38 	struct bpf_spin_lock l;
39 };
40 
41 struct {
42 	__uint(type, BPF_MAP_TYPE_SK_STORAGE);
43 	__uint(max_entries, 0);
44 	__type(key, int);
45 	__type(value, struct val);
46 	__uint(map_flags, BPF_F_NO_PREALLOC);
47 } sk_storage_map SEC(".maps");
48 
49 struct {
50 	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
51 	__uint(max_entries, 1);
52 	__uint(key_size, sizeof(__u32));
53 	__uint(value_size, sizeof(__u32));
54 } jmp_table SEC(".maps");
55 
56 SEC("cgroup/skb")
57 __description("skb->sk: no NULL check")
58 __failure __msg("invalid mem access 'sock_common_or_null'")
59 __failure_unpriv
60 __naked void skb_sk_no_null_check(void)
61 {
62 	asm volatile ("					\
63 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
64 	r0 = *(u32*)(r1 + 0);				\
65 	r0 = 0;						\
66 	exit;						\
67 "	:
68 	: __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
69 	: __clobber_all);
70 }
71 
72 SEC("cgroup/skb")
73 __description("skb->sk: sk->family [non fullsock field]")
74 __success __success_unpriv __retval(0)
75 __naked void sk_family_non_fullsock_field_1(void)
76 {
77 	asm volatile ("					\
78 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
79 	if r1 != 0 goto l0_%=;				\
80 	r0 = 0;						\
81 	exit;						\
82 l0_%=:	r0 = *(u32*)(r1 + %[bpf_sock_family]);		\
83 	r0 = 0;						\
84 	exit;						\
85 "	:
86 	: __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
87 	  __imm_const(bpf_sock_family, offsetof(struct bpf_sock, family))
88 	: __clobber_all);
89 }
90 
91 SEC("socket")
92 __description("skb->sk: sk->rx_queue_mapping [no sign extension]")
93 __success __success_unpriv __retval(0)
94 __naked void sk_rx_queue_mapping_no_sign_ext(void)
95 {
96 	asm volatile ("					\
97 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
98 	if r1 != 0 goto l0_%=;				\
99 	r0 = 0xdead;					\
100 	exit;						\
101 l0_%=:	r0 = *(u32*)(r1 + %[bpf_sock_rx_queue_mapping]);	\
102 	r0 >>= 32;					\
103 	exit;						\
104 "	:
105 	: __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
106 	  __imm_const(bpf_sock_rx_queue_mapping, offsetof(struct bpf_sock, rx_queue_mapping))
107 	: __clobber_all);
108 }
109 
110 SEC("socket")
111 __description("skb->sk: sk->rx_queue_mapping [narrow load mask]")
112 __success __success_unpriv __retval(0)
113 __naked void sk_rx_queue_mapping_narrow_load_mask(void)
114 {
115 	asm volatile ("					\
116 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
117 	if r1 != 0 goto l0_%=;				\
118 	r0 = 0xdead;					\
119 	exit;						\
120 l0_%=:	r0 = *(u16*)(r1 + %[bpf_sock_rx_queue_mapping]);	\
121 	r0 >>= 16;					\
122 	exit;						\
123 "	:
124 	: __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
125 	  __imm_const(bpf_sock_rx_queue_mapping, offsetof(struct bpf_sock, rx_queue_mapping))
126 	: __clobber_all);
127 }
128 
129 SEC("cgroup/skb")
130 __description("skb->sk: sk->type [fullsock field]")
131 __failure __msg("invalid sock_common access")
132 __failure_unpriv
133 __naked void sk_sk_type_fullsock_field_1(void)
134 {
135 	asm volatile ("					\
136 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
137 	if r1 != 0 goto l0_%=;				\
138 	r0 = 0;						\
139 	exit;						\
140 l0_%=:	r0 = *(u32*)(r1 + %[bpf_sock_type]);		\
141 	r0 = 0;						\
142 	exit;						\
143 "	:
144 	: __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
145 	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type))
146 	: __clobber_all);
147 }
148 
149 SEC("cgroup/skb")
150 __description("bpf_sk_fullsock(skb->sk): no !skb->sk check")
151 __failure __msg("Possibly NULL pointer passed to trusted R1")
152 __failure_unpriv
153 __naked void sk_no_skb_sk_check_1(void)
154 {
155 	asm volatile ("					\
156 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
157 	call %[bpf_sk_fullsock];			\
158 	r0 = 0;						\
159 	exit;						\
160 "	:
161 	: __imm(bpf_sk_fullsock),
162 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
163 	: __clobber_all);
164 }
165 
166 SEC("cgroup/skb")
167 __description("sk_fullsock(skb->sk): no NULL check on ret")
168 __failure __msg("invalid mem access 'sock_or_null'")
169 __failure_unpriv
170 __naked void no_null_check_on_ret_1(void)
171 {
172 	asm volatile ("					\
173 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
174 	if r1 != 0 goto l0_%=;				\
175 	r0 = 0;						\
176 	exit;						\
177 l0_%=:	call %[bpf_sk_fullsock];			\
178 	r0 = *(u32*)(r0 + %[bpf_sock_type]);		\
179 	r0 = 0;						\
180 	exit;						\
181 "	:
182 	: __imm(bpf_sk_fullsock),
183 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
184 	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type))
185 	: __clobber_all);
186 }
187 
188 SEC("cgroup/skb")
189 __description("sk_fullsock(skb->sk): sk->type [fullsock field]")
190 __success __success_unpriv __retval(0)
191 __naked void sk_sk_type_fullsock_field_2(void)
192 {
193 	asm volatile ("					\
194 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
195 	if r1 != 0 goto l0_%=;				\
196 	r0 = 0;						\
197 	exit;						\
198 l0_%=:	call %[bpf_sk_fullsock];			\
199 	if r0 != 0 goto l1_%=;				\
200 	r0 = 0;						\
201 	exit;						\
202 l1_%=:	r0 = *(u32*)(r0 + %[bpf_sock_type]);		\
203 	r0 = 0;						\
204 	exit;						\
205 "	:
206 	: __imm(bpf_sk_fullsock),
207 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
208 	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type))
209 	: __clobber_all);
210 }
211 
212 SEC("cgroup/skb")
213 __description("sk_fullsock(skb->sk): sk->family [non fullsock field]")
214 __success __success_unpriv __retval(0)
215 __naked void sk_family_non_fullsock_field_2(void)
216 {
217 	asm volatile ("					\
218 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
219 	if r1 != 0 goto l0_%=;				\
220 	r0 = 0;						\
221 	exit;						\
222 l0_%=:	call %[bpf_sk_fullsock];			\
223 	if r0 != 0 goto l1_%=;				\
224 	exit;						\
225 l1_%=:	r0 = *(u32*)(r0 + %[bpf_sock_family]);		\
226 	r0 = 0;						\
227 	exit;						\
228 "	:
229 	: __imm(bpf_sk_fullsock),
230 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
231 	  __imm_const(bpf_sock_family, offsetof(struct bpf_sock, family))
232 	: __clobber_all);
233 }
234 
235 SEC("cgroup/skb")
236 __description("sk_fullsock(skb->sk): sk->state [narrow load]")
237 __success __success_unpriv __retval(0)
238 __naked void sk_sk_state_narrow_load(void)
239 {
240 	asm volatile ("					\
241 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
242 	if r1 != 0 goto l0_%=;				\
243 	r0 = 0;						\
244 	exit;						\
245 l0_%=:	call %[bpf_sk_fullsock];			\
246 	if r0 != 0 goto l1_%=;				\
247 	r0 = 0;						\
248 	exit;						\
249 l1_%=:	r0 = *(u8*)(r0 + %[bpf_sock_state]);		\
250 	r0 = 0;						\
251 	exit;						\
252 "	:
253 	: __imm(bpf_sk_fullsock),
254 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
255 	  __imm_const(bpf_sock_state, offsetof(struct bpf_sock, state))
256 	: __clobber_all);
257 }
258 
259 SEC("cgroup/skb")
260 __description("sk_fullsock(skb->sk): sk->dst_port [word load] (backward compatibility)")
261 __success __success_unpriv __retval(0)
262 __naked void port_word_load_backward_compatibility(void)
263 {
264 	asm volatile ("					\
265 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
266 	if r1 != 0 goto l0_%=;				\
267 	r0 = 0;						\
268 	exit;						\
269 l0_%=:	call %[bpf_sk_fullsock];			\
270 	if r0 != 0 goto l1_%=;				\
271 	r0 = 0;						\
272 	exit;						\
273 l1_%=:	r0 = *(u32*)(r0 + %[bpf_sock_dst_port]);	\
274 	r0 = 0;						\
275 	exit;						\
276 "	:
277 	: __imm(bpf_sk_fullsock),
278 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
279 	  __imm_const(bpf_sock_dst_port, offsetof(struct bpf_sock, dst_port))
280 	: __clobber_all);
281 }
282 
283 SEC("cgroup/skb")
284 __description("sk_fullsock(skb->sk): sk->dst_port [half load]")
285 __success __success_unpriv __retval(0)
286 __naked void sk_dst_port_half_load(void)
287 {
288 	asm volatile ("					\
289 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
290 	if r1 != 0 goto l0_%=;				\
291 	r0 = 0;						\
292 	exit;						\
293 l0_%=:	call %[bpf_sk_fullsock];			\
294 	if r0 != 0 goto l1_%=;				\
295 	r0 = 0;						\
296 	exit;						\
297 l1_%=:	r0 = *(u16*)(r0 + %[bpf_sock_dst_port]);	\
298 	r0 = 0;						\
299 	exit;						\
300 "	:
301 	: __imm(bpf_sk_fullsock),
302 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
303 	  __imm_const(bpf_sock_dst_port, offsetof(struct bpf_sock, dst_port))
304 	: __clobber_all);
305 }
306 
307 SEC("cgroup/skb")
308 __description("sk_fullsock(skb->sk): sk->dst_port [half load] (invalid)")
309 __failure __msg("invalid sock access")
310 __failure_unpriv
311 __naked void dst_port_half_load_invalid_1(void)
312 {
313 	asm volatile ("					\
314 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
315 	if r1 != 0 goto l0_%=;				\
316 	r0 = 0;						\
317 	exit;						\
318 l0_%=:	call %[bpf_sk_fullsock];			\
319 	if r0 != 0 goto l1_%=;				\
320 	r0 = 0;						\
321 	exit;						\
322 l1_%=:	r0 = *(u16*)(r0 + %[__imm_0]);			\
323 	r0 = 0;						\
324 	exit;						\
325 "	:
326 	: __imm(bpf_sk_fullsock),
327 	  __imm_const(__imm_0, offsetof(struct bpf_sock, dst_port) + 2),
328 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
329 	: __clobber_all);
330 }
331 
332 SEC("cgroup/skb")
333 __description("sk_fullsock(skb->sk): sk->dst_port [byte load]")
334 __success __success_unpriv __retval(0)
335 __naked void sk_dst_port_byte_load(void)
336 {
337 	asm volatile ("					\
338 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
339 	if r1 != 0 goto l0_%=;				\
340 	r0 = 0;						\
341 	exit;						\
342 l0_%=:	call %[bpf_sk_fullsock];			\
343 	if r0 != 0 goto l1_%=;				\
344 	r0 = 0;						\
345 	exit;						\
346 l1_%=:	r2 = *(u8*)(r0 + %[bpf_sock_dst_port]);		\
347 	r2 = *(u8*)(r0 + %[__imm_0]);			\
348 	r0 = 0;						\
349 	exit;						\
350 "	:
351 	: __imm(bpf_sk_fullsock),
352 	  __imm_const(__imm_0, offsetof(struct bpf_sock, dst_port) + 1),
353 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
354 	  __imm_const(bpf_sock_dst_port, offsetof(struct bpf_sock, dst_port))
355 	: __clobber_all);
356 }
357 
358 SEC("cgroup/skb")
359 __description("sk_fullsock(skb->sk): sk->dst_port [byte load] (invalid)")
360 __failure __msg("invalid sock access")
361 __failure_unpriv
362 __naked void dst_port_byte_load_invalid(void)
363 {
364 	asm volatile ("					\
365 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
366 	if r1 != 0 goto l0_%=;				\
367 	r0 = 0;						\
368 	exit;						\
369 l0_%=:	call %[bpf_sk_fullsock];			\
370 	if r0 != 0 goto l1_%=;				\
371 	r0 = 0;						\
372 	exit;						\
373 l1_%=:	r0 = *(u8*)(r0 + %[__imm_0]);			\
374 	r0 = 0;						\
375 	exit;						\
376 "	:
377 	: __imm(bpf_sk_fullsock),
378 	  __imm_const(__imm_0, offsetof(struct bpf_sock, dst_port) + 2),
379 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
380 	: __clobber_all);
381 }
382 
383 SEC("cgroup/skb")
384 __description("sk_fullsock(skb->sk): past sk->dst_port [half load] (invalid)")
385 __failure __msg("invalid sock access")
386 __failure_unpriv
387 __naked void dst_port_half_load_invalid_2(void)
388 {
389 	asm volatile ("					\
390 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
391 	if r1 != 0 goto l0_%=;				\
392 	r0 = 0;						\
393 	exit;						\
394 l0_%=:	call %[bpf_sk_fullsock];			\
395 	if r0 != 0 goto l1_%=;				\
396 	r0 = 0;						\
397 	exit;						\
398 l1_%=:	r0 = *(u16*)(r0 + %[bpf_sock_dst_port__end]);	\
399 	r0 = 0;						\
400 	exit;						\
401 "	:
402 	: __imm(bpf_sk_fullsock),
403 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
404 	  __imm_const(bpf_sock_dst_port__end, offsetofend(struct bpf_sock, dst_port))
405 	: __clobber_all);
406 }
407 
408 SEC("cgroup/skb")
409 __description("sk_fullsock(skb->sk): sk->dst_ip6 [load 2nd byte]")
410 __success __success_unpriv __retval(0)
411 __naked void dst_ip6_load_2nd_byte(void)
412 {
413 	asm volatile ("					\
414 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
415 	if r1 != 0 goto l0_%=;				\
416 	r0 = 0;						\
417 	exit;						\
418 l0_%=:	call %[bpf_sk_fullsock];			\
419 	if r0 != 0 goto l1_%=;				\
420 	r0 = 0;						\
421 	exit;						\
422 l1_%=:	r0 = *(u8*)(r0 + %[__imm_0]);			\
423 	r0 = 0;						\
424 	exit;						\
425 "	:
426 	: __imm(bpf_sk_fullsock),
427 	  __imm_const(__imm_0, offsetof(struct bpf_sock, dst_ip6[0]) + 1),
428 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
429 	: __clobber_all);
430 }
431 
432 SEC("cgroup/skb")
433 __description("sk_fullsock(skb->sk): sk->type [narrow load]")
434 __success __success_unpriv __retval(0)
435 __naked void sk_sk_type_narrow_load(void)
436 {
437 	asm volatile ("					\
438 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
439 	if r1 != 0 goto l0_%=;				\
440 	r0 = 0;						\
441 	exit;						\
442 l0_%=:	call %[bpf_sk_fullsock];			\
443 	if r0 != 0 goto l1_%=;				\
444 	r0 = 0;						\
445 	exit;						\
446 l1_%=:	r0 = *(u8*)(r0 + %[bpf_sock_type]);		\
447 	r0 = 0;						\
448 	exit;						\
449 "	:
450 	: __imm(bpf_sk_fullsock),
451 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
452 	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type))
453 	: __clobber_all);
454 }
455 
456 SEC("cgroup/skb")
457 __description("sk_fullsock(skb->sk): sk->protocol [narrow load]")
458 __success __success_unpriv __retval(0)
459 __naked void sk_sk_protocol_narrow_load(void)
460 {
461 	asm volatile ("					\
462 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
463 	if r1 != 0 goto l0_%=;				\
464 	r0 = 0;						\
465 	exit;						\
466 l0_%=:	call %[bpf_sk_fullsock];			\
467 	if r0 != 0 goto l1_%=;				\
468 	r0 = 0;						\
469 	exit;						\
470 l1_%=:	r0 = *(u8*)(r0 + %[bpf_sock_protocol]);		\
471 	r0 = 0;						\
472 	exit;						\
473 "	:
474 	: __imm(bpf_sk_fullsock),
475 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
476 	  __imm_const(bpf_sock_protocol, offsetof(struct bpf_sock, protocol))
477 	: __clobber_all);
478 }
479 
480 SEC("cgroup/skb")
481 __description("sk_fullsock(skb->sk): beyond last field")
482 __failure __msg("invalid sock access")
483 __failure_unpriv
484 __naked void skb_sk_beyond_last_field_1(void)
485 {
486 	asm volatile ("					\
487 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
488 	if r1 != 0 goto l0_%=;				\
489 	r0 = 0;						\
490 	exit;						\
491 l0_%=:	call %[bpf_sk_fullsock];			\
492 	if r0 != 0 goto l1_%=;				\
493 	r0 = 0;						\
494 	exit;						\
495 l1_%=:	r0 = *(u32*)(r0 + %[bpf_sock_rx_queue_mapping__end]);\
496 	r0 = 0;						\
497 	exit;						\
498 "	:
499 	: __imm(bpf_sk_fullsock),
500 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
501 	  __imm_const(bpf_sock_rx_queue_mapping__end, offsetofend(struct bpf_sock, rx_queue_mapping))
502 	: __clobber_all);
503 }
504 
505 SEC("cgroup/skb")
506 __description("bpf_tcp_sock(skb->sk): no !skb->sk check")
507 __failure __msg("Possibly NULL pointer passed to trusted R1")
508 __failure_unpriv
509 __naked void sk_no_skb_sk_check_2(void)
510 {
511 	asm volatile ("					\
512 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
513 	call %[bpf_tcp_sock];				\
514 	r0 = 0;						\
515 	exit;						\
516 "	:
517 	: __imm(bpf_tcp_sock),
518 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
519 	: __clobber_all);
520 }
521 
522 SEC("cgroup/skb")
523 __description("bpf_tcp_sock(skb->sk): no NULL check on ret")
524 __failure __msg("invalid mem access 'tcp_sock_or_null'")
525 __failure_unpriv
526 __naked void no_null_check_on_ret_2(void)
527 {
528 	asm volatile ("					\
529 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
530 	if r1 != 0 goto l0_%=;				\
531 	r0 = 0;						\
532 	exit;						\
533 l0_%=:	call %[bpf_tcp_sock];				\
534 	r0 = *(u32*)(r0 + %[bpf_tcp_sock_snd_cwnd]);	\
535 	r0 = 0;						\
536 	exit;						\
537 "	:
538 	: __imm(bpf_tcp_sock),
539 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
540 	  __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd))
541 	: __clobber_all);
542 }
543 
544 SEC("cgroup/skb")
545 __description("bpf_tcp_sock(skb->sk): tp->snd_cwnd")
546 __success __success_unpriv __retval(0)
547 __naked void skb_sk_tp_snd_cwnd_1(void)
548 {
549 	asm volatile ("					\
550 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
551 	if r1 != 0 goto l0_%=;				\
552 	r0 = 0;						\
553 	exit;						\
554 l0_%=:	call %[bpf_tcp_sock];				\
555 	if r0 != 0 goto l1_%=;				\
556 	exit;						\
557 l1_%=:	r0 = *(u32*)(r0 + %[bpf_tcp_sock_snd_cwnd]);	\
558 	r0 = 0;						\
559 	exit;						\
560 "	:
561 	: __imm(bpf_tcp_sock),
562 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
563 	  __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd))
564 	: __clobber_all);
565 }
566 
567 SEC("cgroup/skb")
568 __description("bpf_tcp_sock(skb->sk): tp->bytes_acked")
569 __success __success_unpriv __retval(0)
570 __naked void skb_sk_tp_bytes_acked(void)
571 {
572 	asm volatile ("					\
573 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
574 	if r1 != 0 goto l0_%=;				\
575 	r0 = 0;						\
576 	exit;						\
577 l0_%=:	call %[bpf_tcp_sock];				\
578 	if r0 != 0 goto l1_%=;				\
579 	exit;						\
580 l1_%=:	r0 = *(u64*)(r0 + %[bpf_tcp_sock_bytes_acked]);	\
581 	r0 = 0;						\
582 	exit;						\
583 "	:
584 	: __imm(bpf_tcp_sock),
585 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
586 	  __imm_const(bpf_tcp_sock_bytes_acked, offsetof(struct bpf_tcp_sock, bytes_acked))
587 	: __clobber_all);
588 }
589 
590 SEC("cgroup/skb")
591 __description("bpf_tcp_sock(skb->sk): beyond last field")
592 __failure __msg("invalid tcp_sock access")
593 __failure_unpriv
594 __naked void skb_sk_beyond_last_field_2(void)
595 {
596 	asm volatile ("					\
597 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
598 	if r1 != 0 goto l0_%=;				\
599 	r0 = 0;						\
600 	exit;						\
601 l0_%=:	call %[bpf_tcp_sock];				\
602 	if r0 != 0 goto l1_%=;				\
603 	exit;						\
604 l1_%=:	r0 = *(u64*)(r0 + %[bpf_tcp_sock_bytes_acked__end]);\
605 	r0 = 0;						\
606 	exit;						\
607 "	:
608 	: __imm(bpf_tcp_sock),
609 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
610 	  __imm_const(bpf_tcp_sock_bytes_acked__end, offsetofend(struct bpf_tcp_sock, bytes_acked))
611 	: __clobber_all);
612 }
613 
614 SEC("cgroup/skb")
615 __description("bpf_tcp_sock(skb->sk): narrow load of tp->bytes_received")
616 __failure __msg("invalid tcp_sock access")
617 __failure_unpriv
618 __naked void skb_sk_tp_bytes_received_narrow(void)
619 {
620 	asm volatile ("					\
621 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
622 	if r1 != 0 goto l0_%=;				\
623 	r0 = 0;						\
624 	exit;						\
625 l0_%=:	call %[bpf_tcp_sock];				\
626 	if r0 != 0 goto l1_%=;				\
627 	exit;						\
628 l1_%=:	r0 = *(u32*)(r0 + %[off]);			\
629 	r0 = 0;						\
630 	exit;						\
631 "	:
632 	: __imm(bpf_tcp_sock),
633 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
634 	  __imm_const(off, offsetof(struct bpf_tcp_sock, bytes_received) + 4)
635 	: __clobber_all);
636 }
637 
638 SEC("cgroup/skb")
639 __description("bpf_tcp_sock(skb->sk): narrow load of tp->bytes_acked")
640 __failure __msg("invalid tcp_sock access")
641 __failure_unpriv
642 __naked void skb_sk_tp_bytes_acked_narrow(void)
643 {
644 	asm volatile ("					\
645 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
646 	if r1 != 0 goto l0_%=;				\
647 	r0 = 0;						\
648 	exit;						\
649 l0_%=:	call %[bpf_tcp_sock];				\
650 	if r0 != 0 goto l1_%=;				\
651 	exit;						\
652 l1_%=:	r0 = *(u32*)(r0 + %[off]);			\
653 	r0 = 0;						\
654 	exit;						\
655 "	:
656 	: __imm(bpf_tcp_sock),
657 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
658 	  __imm_const(off, offsetof(struct bpf_tcp_sock, bytes_acked) + 4)
659 	: __clobber_all);
660 }
661 
662 SEC("cgroup/skb")
663 __description("bpf_tcp_sock(bpf_sk_fullsock(skb->sk)): tp->snd_cwnd")
664 __success __success_unpriv __retval(0)
665 __naked void skb_sk_tp_snd_cwnd_2(void)
666 {
667 	asm volatile ("					\
668 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
669 	if r1 != 0 goto l0_%=;				\
670 	r0 = 0;						\
671 	exit;						\
672 l0_%=:	call %[bpf_sk_fullsock];			\
673 	if r0 != 0 goto l1_%=;				\
674 	exit;						\
675 l1_%=:	r1 = r0;					\
676 	call %[bpf_tcp_sock];				\
677 	if r0 != 0 goto l2_%=;				\
678 	exit;						\
679 l2_%=:	r0 = *(u32*)(r0 + %[bpf_tcp_sock_snd_cwnd]);	\
680 	r0 = 0;						\
681 	exit;						\
682 "	:
683 	: __imm(bpf_sk_fullsock),
684 	  __imm(bpf_tcp_sock),
685 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk)),
686 	  __imm_const(bpf_tcp_sock_snd_cwnd, offsetof(struct bpf_tcp_sock, snd_cwnd))
687 	: __clobber_all);
688 }
689 
690 SEC("tc")
691 __description("bpf_sk_release(skb->sk)")
692 __failure __msg("release function bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1")
693 __naked void bpf_sk_release_skb_sk(void)
694 {
695 	asm volatile ("					\
696 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
697 	if r1 == 0 goto l0_%=;				\
698 	call %[bpf_sk_release];				\
699 l0_%=:	r0 = 0;						\
700 	exit;						\
701 "	:
702 	: __imm(bpf_sk_release),
703 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
704 	: __clobber_all);
705 }
706 
707 SEC("tc")
708 __description("bpf_sk_release(bpf_sk_fullsock(skb->sk))")
709 __failure __msg("release function bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1")
710 __naked void bpf_sk_fullsock_skb_sk(void)
711 {
712 	asm volatile ("					\
713 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
714 	if r1 != 0 goto l0_%=;				\
715 	r0 = 0;						\
716 	exit;						\
717 l0_%=:	call %[bpf_sk_fullsock];			\
718 	if r0 != 0 goto l1_%=;				\
719 	exit;						\
720 l1_%=:	r1 = r0;					\
721 	call %[bpf_sk_release];				\
722 	r0 = 1;						\
723 	exit;						\
724 "	:
725 	: __imm(bpf_sk_fullsock),
726 	  __imm(bpf_sk_release),
727 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
728 	: __clobber_all);
729 }
730 
731 SEC("tc")
732 __description("bpf_sk_release(bpf_tcp_sock(skb->sk))")
733 __failure __msg("release function bpf_sk_release expects referenced PTR_TO_BTF_ID passed to R1")
734 __naked void bpf_tcp_sock_skb_sk(void)
735 {
736 	asm volatile ("					\
737 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
738 	if r1 != 0 goto l0_%=;				\
739 	r0 = 0;						\
740 	exit;						\
741 l0_%=:	call %[bpf_tcp_sock];				\
742 	if r0 != 0 goto l1_%=;				\
743 	exit;						\
744 l1_%=:	r1 = r0;					\
745 	call %[bpf_sk_release];				\
746 	r0 = 1;						\
747 	exit;						\
748 "	:
749 	: __imm(bpf_sk_release),
750 	  __imm(bpf_tcp_sock),
751 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
752 	: __clobber_all);
753 }
754 
755 SEC("tc")
756 __description("sk_storage_get(map, skb->sk, NULL, 0): value == NULL")
757 __success __retval(0)
758 __naked void sk_null_0_value_null(void)
759 {
760 	asm volatile ("					\
761 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
762 	if r1 != 0 goto l0_%=;				\
763 	r0 = 0;						\
764 	exit;						\
765 l0_%=:	call %[bpf_sk_fullsock];			\
766 	if r0 != 0 goto l1_%=;				\
767 	r0 = 0;						\
768 	exit;						\
769 l1_%=:	r4 = 0;						\
770 	r3 = 0;						\
771 	r2 = r0;					\
772 	r1 = %[sk_storage_map] ll;			\
773 	call %[bpf_sk_storage_get];			\
774 	r0 = 0;						\
775 	exit;						\
776 "	:
777 	: __imm(bpf_sk_fullsock),
778 	  __imm(bpf_sk_storage_get),
779 	  __imm_addr(sk_storage_map),
780 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
781 	: __clobber_all);
782 }
783 
784 SEC("tc")
785 __description("sk_storage_get(map, skb->sk, 1, 1): value == 1")
786 __failure __msg("R3 type=scalar expected=fp")
787 __naked void sk_1_1_value_1(void)
788 {
789 	asm volatile ("					\
790 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
791 	if r1 != 0 goto l0_%=;				\
792 	r0 = 0;						\
793 	exit;						\
794 l0_%=:	call %[bpf_sk_fullsock];			\
795 	if r0 != 0 goto l1_%=;				\
796 	r0 = 0;						\
797 	exit;						\
798 l1_%=:	r4 = 1;						\
799 	r3 = 1;						\
800 	r2 = r0;					\
801 	r1 = %[sk_storage_map] ll;			\
802 	call %[bpf_sk_storage_get];			\
803 	r0 = 0;						\
804 	exit;						\
805 "	:
806 	: __imm(bpf_sk_fullsock),
807 	  __imm(bpf_sk_storage_get),
808 	  __imm_addr(sk_storage_map),
809 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
810 	: __clobber_all);
811 }
812 
813 SEC("tc")
814 __description("sk_storage_get(map, skb->sk, &stack_value, 1): stack_value")
815 __success __retval(0)
816 __naked void stack_value_1_stack_value(void)
817 {
818 	asm volatile ("					\
819 	r2 = 0;						\
820 	*(u64*)(r10 - 8) = r2;				\
821 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
822 	if r1 != 0 goto l0_%=;				\
823 	r0 = 0;						\
824 	exit;						\
825 l0_%=:	call %[bpf_sk_fullsock];			\
826 	if r0 != 0 goto l1_%=;				\
827 	r0 = 0;						\
828 	exit;						\
829 l1_%=:	r4 = 1;						\
830 	r3 = r10;					\
831 	r3 += -8;					\
832 	r2 = r0;					\
833 	r1 = %[sk_storage_map] ll;			\
834 	call %[bpf_sk_storage_get];			\
835 	r0 = 0;						\
836 	exit;						\
837 "	:
838 	: __imm(bpf_sk_fullsock),
839 	  __imm(bpf_sk_storage_get),
840 	  __imm_addr(sk_storage_map),
841 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
842 	: __clobber_all);
843 }
844 
845 SEC("tc")
846 __description("bpf_map_lookup_elem(smap, &key)")
847 __failure __msg("cannot pass map_type 24 into func bpf_map_lookup_elem")
848 __naked void map_lookup_elem_smap_key(void)
849 {
850 	asm volatile ("					\
851 	r1 = 0;						\
852 	*(u32*)(r10 - 4) = r1;				\
853 	r2 = r10;					\
854 	r2 += -4;					\
855 	r1 = %[sk_storage_map] ll;			\
856 	call %[bpf_map_lookup_elem];			\
857 	r0 = 0;						\
858 	exit;						\
859 "	:
860 	: __imm(bpf_map_lookup_elem),
861 	  __imm_addr(sk_storage_map)
862 	: __clobber_all);
863 }
864 
865 SEC("xdp")
866 __description("bpf_map_lookup_elem(xskmap, &key); xs->queue_id")
867 __success __retval(0)
868 __naked void xskmap_key_xs_queue_id(void)
869 {
870 	asm volatile ("					\
871 	r1 = 0;						\
872 	*(u32*)(r10 - 8) = r1;				\
873 	r2 = r10;					\
874 	r2 += -8;					\
875 	r1 = %[map_xskmap] ll;				\
876 	call %[bpf_map_lookup_elem];			\
877 	if r0 != 0 goto l0_%=;				\
878 	exit;						\
879 l0_%=:	r0 = *(u32*)(r0 + %[bpf_xdp_sock_queue_id]);	\
880 	r0 = 0;						\
881 	exit;						\
882 "	:
883 	: __imm(bpf_map_lookup_elem),
884 	  __imm_addr(map_xskmap),
885 	  __imm_const(bpf_xdp_sock_queue_id, offsetof(struct bpf_xdp_sock, queue_id))
886 	: __clobber_all);
887 }
888 
889 SEC("sk_skb")
890 __description("bpf_map_lookup_elem(sockmap, &key)")
891 __failure __msg("Unreleased reference id=2 alloc_insn=6")
892 __naked void map_lookup_elem_sockmap_key(void)
893 {
894 	asm volatile ("					\
895 	r1 = 0;						\
896 	*(u32*)(r10 - 4) = r1;				\
897 	r2 = r10;					\
898 	r2 += -4;					\
899 	r1 = %[map_sockmap] ll;				\
900 	call %[bpf_map_lookup_elem];			\
901 	r0 = 0;						\
902 	exit;						\
903 "	:
904 	: __imm(bpf_map_lookup_elem),
905 	  __imm_addr(map_sockmap)
906 	: __clobber_all);
907 }
908 
909 SEC("sk_skb")
910 __description("bpf_map_lookup_elem(sockhash, &key)")
911 __failure __msg("Unreleased reference id=2 alloc_insn=6")
912 __naked void map_lookup_elem_sockhash_key(void)
913 {
914 	asm volatile ("					\
915 	r1 = 0;						\
916 	*(u32*)(r10 - 4) = r1;				\
917 	r2 = r10;					\
918 	r2 += -4;					\
919 	r1 = %[map_sockhash] ll;			\
920 	call %[bpf_map_lookup_elem];			\
921 	r0 = 0;						\
922 	exit;						\
923 "	:
924 	: __imm(bpf_map_lookup_elem),
925 	  __imm_addr(map_sockhash)
926 	: __clobber_all);
927 }
928 
929 SEC("sk_skb")
930 __description("bpf_map_lookup_elem(sockmap, &key); sk->type [fullsock field]; bpf_sk_release(sk)")
931 __success
932 __naked void field_bpf_sk_release_sk_1(void)
933 {
934 	asm volatile ("					\
935 	r1 = 0;						\
936 	*(u32*)(r10 - 4) = r1;				\
937 	r2 = r10;					\
938 	r2 += -4;					\
939 	r1 = %[map_sockmap] ll;				\
940 	call %[bpf_map_lookup_elem];			\
941 	if r0 != 0 goto l0_%=;				\
942 	exit;						\
943 l0_%=:	r1 = r0;					\
944 	r0 = *(u32*)(r0 + %[bpf_sock_type]);		\
945 	call %[bpf_sk_release];				\
946 	exit;						\
947 "	:
948 	: __imm(bpf_map_lookup_elem),
949 	  __imm(bpf_sk_release),
950 	  __imm_addr(map_sockmap),
951 	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type))
952 	: __clobber_all);
953 }
954 
955 SEC("sk_skb")
956 __description("bpf_map_lookup_elem(sockhash, &key); sk->type [fullsock field]; bpf_sk_release(sk)")
957 __success
958 __naked void field_bpf_sk_release_sk_2(void)
959 {
960 	asm volatile ("					\
961 	r1 = 0;						\
962 	*(u32*)(r10 - 4) = r1;				\
963 	r2 = r10;					\
964 	r2 += -4;					\
965 	r1 = %[map_sockhash] ll;			\
966 	call %[bpf_map_lookup_elem];			\
967 	if r0 != 0 goto l0_%=;				\
968 	exit;						\
969 l0_%=:	r1 = r0;					\
970 	r0 = *(u32*)(r0 + %[bpf_sock_type]);		\
971 	call %[bpf_sk_release];				\
972 	exit;						\
973 "	:
974 	: __imm(bpf_map_lookup_elem),
975 	  __imm(bpf_sk_release),
976 	  __imm_addr(map_sockhash),
977 	  __imm_const(bpf_sock_type, offsetof(struct bpf_sock, type))
978 	: __clobber_all);
979 }
980 
981 SEC("sk_reuseport")
982 __description("bpf_sk_select_reuseport(ctx, reuseport_array, &key, flags)")
983 __success
984 __naked void ctx_reuseport_array_key_flags(void)
985 {
986 	asm volatile ("					\
987 	r4 = 0;						\
988 	r2 = 0;						\
989 	*(u32*)(r10 - 4) = r2;				\
990 	r3 = r10;					\
991 	r3 += -4;					\
992 	r2 = %[map_reuseport_array] ll;			\
993 	call %[bpf_sk_select_reuseport];		\
994 	exit;						\
995 "	:
996 	: __imm(bpf_sk_select_reuseport),
997 	  __imm_addr(map_reuseport_array)
998 	: __clobber_all);
999 }
1000 
1001 SEC("sk_reuseport")
1002 __description("bpf_sk_select_reuseport(ctx, sockmap, &key, flags)")
1003 __success
1004 __naked void reuseport_ctx_sockmap_key_flags(void)
1005 {
1006 	asm volatile ("					\
1007 	r4 = 0;						\
1008 	r2 = 0;						\
1009 	*(u32*)(r10 - 4) = r2;				\
1010 	r3 = r10;					\
1011 	r3 += -4;					\
1012 	r2 = %[map_sockmap] ll;				\
1013 	call %[bpf_sk_select_reuseport];		\
1014 	exit;						\
1015 "	:
1016 	: __imm(bpf_sk_select_reuseport),
1017 	  __imm_addr(map_sockmap)
1018 	: __clobber_all);
1019 }
1020 
1021 SEC("sk_reuseport")
1022 __description("bpf_sk_select_reuseport(ctx, sockhash, &key, flags)")
1023 __success
1024 __naked void reuseport_ctx_sockhash_key_flags(void)
1025 {
1026 	asm volatile ("					\
1027 	r4 = 0;						\
1028 	r2 = 0;						\
1029 	*(u32*)(r10 - 4) = r2;				\
1030 	r3 = r10;					\
1031 	r3 += -4;					\
1032 	r2 = %[map_sockmap] ll;				\
1033 	call %[bpf_sk_select_reuseport];		\
1034 	exit;						\
1035 "	:
1036 	: __imm(bpf_sk_select_reuseport),
1037 	  __imm_addr(map_sockmap)
1038 	: __clobber_all);
1039 }
1040 
1041 SEC("tc")
1042 __description("mark null check on return value of bpf_skc_to helpers")
1043 __failure __msg("invalid mem access")
1044 __naked void of_bpf_skc_to_helpers(void)
1045 {
1046 	asm volatile ("					\
1047 	r1 = *(u64*)(r1 + %[__sk_buff_sk]);		\
1048 	if r1 != 0 goto l0_%=;				\
1049 	r0 = 0;						\
1050 	exit;						\
1051 l0_%=:	r6 = r1;					\
1052 	call %[bpf_skc_to_tcp_sock];			\
1053 	r7 = r0;					\
1054 	r1 = r6;					\
1055 	call %[bpf_skc_to_tcp_request_sock];		\
1056 	r8 = r0;					\
1057 	if r8 != 0 goto l1_%=;				\
1058 	r0 = 0;						\
1059 	exit;						\
1060 l1_%=:	r0 = *(u8*)(r7 + 0);				\
1061 	exit;						\
1062 "	:
1063 	: __imm(bpf_skc_to_tcp_request_sock),
1064 	  __imm(bpf_skc_to_tcp_sock),
1065 	  __imm_const(__sk_buff_sk, offsetof(struct __sk_buff, sk))
1066 	: __clobber_all);
1067 }
1068 
1069 SEC("cgroup/post_bind4")
1070 __description("sk->src_ip6[0] [load 1st byte]")
1071 __failure __msg("invalid bpf_context access off=28 size=2")
1072 __naked void post_bind4_read_src_ip6(void)
1073 {
1074 	asm volatile ("					\
1075 	r6 = r1;					\
1076 	r7 = *(u16*)(r6 + %[bpf_sock_src_ip6_0]);	\
1077 	r0 = 1;						\
1078 	exit;						\
1079 "	:
1080 	: __imm_const(bpf_sock_src_ip6_0, offsetof(struct bpf_sock, src_ip6[0]))
1081 	: __clobber_all);
1082 }
1083 
1084 SEC("cgroup/post_bind4")
1085 __description("sk->mark [load mark]")
1086 __failure __msg("invalid bpf_context access off=16 size=2")
1087 __naked void post_bind4_read_mark(void)
1088 {
1089 	asm volatile ("					\
1090 	r6 = r1;					\
1091 	r7 = *(u16*)(r6 + %[bpf_sock_mark]);		\
1092 	r0 = 1;						\
1093 	exit;						\
1094 "	:
1095 	: __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark))
1096 	: __clobber_all);
1097 }
1098 
1099 SEC("cgroup/post_bind6")
1100 __description("sk->src_ip4 [load src_ip4]")
1101 __failure __msg("invalid bpf_context access off=24 size=2")
1102 __naked void post_bind6_read_src_ip4(void)
1103 {
1104 	asm volatile ("					\
1105 	r6 = r1;					\
1106 	r7 = *(u16*)(r6 + %[bpf_sock_src_ip4]);		\
1107 	r0 = 1;						\
1108 	exit;						\
1109 "	:
1110 	: __imm_const(bpf_sock_src_ip4, offsetof(struct bpf_sock, src_ip4))
1111 	: __clobber_all);
1112 }
1113 
1114 SEC("cgroup/sock_create")
1115 __description("sk->src_port [word load]")
1116 __failure __msg("invalid bpf_context access off=44 size=2")
1117 __naked void sock_create_read_src_port(void)
1118 {
1119 	asm volatile ("					\
1120 	r6 = r1;					\
1121 	r7 = *(u16*)(r6 + %[bpf_sock_src_port]);	\
1122 	r0 = 1;						\
1123 	exit;						\
1124 "	:
1125 	: __imm_const(bpf_sock_src_port, offsetof(struct bpf_sock, src_port))
1126 	: __clobber_all);
1127 }
1128 
1129 __noinline
1130 long skb_pull_data2(struct __sk_buff *sk, __u32 len)
1131 {
1132 	return bpf_skb_pull_data(sk, len);
1133 }
1134 
1135 __noinline
1136 long skb_pull_data1(struct __sk_buff *sk, __u32 len)
1137 {
1138 	return skb_pull_data2(sk, len);
1139 }
1140 
1141 /* global function calls bpf_skb_pull_data(), which invalidates packet
1142  * pointers established before global function call.
1143  */
1144 SEC("tc")
1145 __failure __msg("invalid mem access")
1146 int invalidate_pkt_pointers_from_global_func(struct __sk_buff *sk)
1147 {
1148 	int *p = (void *)(long)sk->data;
1149 
1150 	if ((void *)(p + 1) > (void *)(long)sk->data_end)
1151 		return TCX_DROP;
1152 	skb_pull_data1(sk, 0);
1153 	*p = 42; /* this is unsafe */
1154 	return TCX_PASS;
1155 }
1156 
1157 __noinline
1158 long xdp_pull_data2(struct xdp_md *x, __u32 len)
1159 {
1160 	return bpf_xdp_pull_data(x, len);
1161 }
1162 
1163 __noinline
1164 long xdp_pull_data1(struct xdp_md *x, __u32 len)
1165 {
1166 	return xdp_pull_data2(x, len);
1167 }
1168 
1169 /* global function calls bpf_xdp_pull_data(), which invalidates packet
1170  * pointers established before global function call.
1171  */
1172 SEC("xdp")
1173 __failure __msg("invalid mem access")
1174 int invalidate_xdp_pkt_pointers_from_global_func(struct xdp_md *x)
1175 {
1176 	int *p = (void *)(long)x->data;
1177 
1178 	if ((void *)(p + 1) > (void *)(long)x->data_end)
1179 		return XDP_DROP;
1180 	xdp_pull_data1(x, 0);
1181 	*p = 42; /* this is unsafe */
1182 	return XDP_PASS;
1183 }
1184 
1185 /* XDP packet changing kfunc calls invalidate packet pointers */
1186 SEC("xdp")
1187 __failure __msg("invalid mem access")
1188 int invalidate_xdp_pkt_pointers(struct xdp_md *x)
1189 {
1190 	int *p = (void *)(long)x->data;
1191 
1192 	if ((void *)(p + 1) > (void *)(long)x->data_end)
1193 		return XDP_DROP;
1194 	bpf_xdp_pull_data(x, 0);
1195 	*p = 42; /* this is unsafe */
1196 	return XDP_PASS;
1197 }
1198 
1199 __noinline
1200 int tail_call(struct __sk_buff *sk)
1201 {
1202 	bpf_tail_call_static(sk, &jmp_table, 0);
1203 	return 0;
1204 }
1205 
1206 static __noinline
1207 int static_tail_call(struct __sk_buff *sk)
1208 {
1209 	int ret = 0;
1210 
1211 	bpf_tail_call_static(sk, &jmp_table, 0);
1212 	barrier_var(ret);
1213 	return ret;
1214 }
1215 
1216 /* Tail calls in sub-programs invalidate packet pointers. */
1217 SEC("tc")
1218 __failure __msg("invalid mem access")
1219 int invalidate_pkt_pointers_by_global_tail_call(struct __sk_buff *sk)
1220 {
1221 	int *p = (void *)(long)sk->data;
1222 
1223 	if ((void *)(p + 1) > (void *)(long)sk->data_end)
1224 		return TCX_DROP;
1225 	tail_call(sk);
1226 	*p = 42; /* this is unsafe */
1227 	return TCX_PASS;
1228 }
1229 
1230 /* Tail calls in static sub-programs invalidate packet pointers. */
1231 SEC("tc")
1232 __failure __msg("invalid mem access")
1233 int invalidate_pkt_pointers_by_static_tail_call(struct __sk_buff *sk)
1234 {
1235 	int *p = (void *)(long)sk->data;
1236 	int ret;
1237 
1238 	if ((void *)(p + 1) > (void *)(long)sk->data_end)
1239 		return TCX_DROP;
1240 	ret = static_tail_call(sk);
1241 	__sink(ret);
1242 	*p = 42; /* this is unsafe */
1243 	return TCX_PASS;
1244 }
1245 
1246 /* Direct tail calls do not invalidate packet pointers. */
1247 SEC("tc")
1248 __success
1249 int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk)
1250 {
1251 	int *p = (void *)(long)sk->data;
1252 
1253 	if ((void *)(p + 1) > (void *)(long)sk->data_end)
1254 		return TCX_DROP;
1255 	bpf_tail_call_static(sk, &jmp_table, 0);
1256 	*p = 42; /* this is NOT unsafe: tail calls don't return */
1257 	return TCX_PASS;
1258 }
1259 
1260 char _license[] SEC("license") = "GPL";
1261