File Index
Files and directories
Sign in
FILE

verifier_direct_packet_access.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/verifier_direct_packet_access.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Converted from tools/testing/selftests/bpf/verifier/direct_packet_access.c */
  3
  4#include <linux/if_ether.h>
  5#include <linux/bpf.h>
  6#include <bpf/bpf_helpers.h>
  7#include "bpf_misc.h"
  8
  9SEC("tc")
 10__description("pkt_end - pkt_start is allowed")
 11__success __retval(TEST_DATA_LEN)
 12__naked void end_pkt_start_is_allowed(void)
 13{
 14	asm volatile ("					\
 15	r0 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
 16	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
 17	r0 -= r2;					\
 18	exit;						\
 19"	:
 20	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
 21	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
 22	: __clobber_all);
 23}
 24
 25SEC("tc")
 26__description("direct packet access: test1")
 27__success __retval(0)
 28__naked void direct_packet_access_test1(void)
 29{
 30	asm volatile ("					\
 31	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
 32	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
 33	r0 = r2;					\
 34	r0 += 8;					\
 35	if r0 > r3 goto l0_%=;				\
 36	r0 = *(u8*)(r2 + 0);				\
 37l0_%=:	r0 = 0;						\
 38	exit;						\
 39"	:
 40	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
 41	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
 42	: __clobber_all);
 43}
 44
 45SEC("tc")
 46__description("direct packet access: test2")
 47__success __retval(0)
 48__naked void direct_packet_access_test2(void)
 49{
 50	asm volatile ("					\
 51	r0 = 1;						\
 52	r4 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
 53	r3 = *(u32*)(r1 + %[__sk_buff_data]);		\
 54	r5 = r3;					\
 55	r5 += 14;					\
 56	if r5 > r4 goto l0_%=;				\
 57	r0 = *(u8*)(r3 + 7);				\
 58	r4 = *(u8*)(r3 + 12);				\
 59	r4 *= 14;					\
 60	r3 = *(u32*)(r1 + %[__sk_buff_data]);		\
 61	r3 += r4;					\
 62	r2 = *(u32*)(r1 + %[__sk_buff_len]);		\
 63	r2 <<= 49;					\
 64	r2 >>= 49;					\
 65	r3 += r2;					\
 66	r2 = r3;					\
 67	r2 += 8;					\
 68	r1 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
 69	if r2 > r1 goto l1_%=;				\
 70	r1 = *(u8*)(r3 + 4);				\
 71l1_%=:	r0 = 0;						\
 72l0_%=:	exit;						\
 73"	:
 74	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
 75	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),
 76	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 77	: __clobber_all);
 78}
 79
 80SEC("socket")
 81__description("direct packet access: test3")
 82__failure __msg("invalid bpf_context access off=76")
 83__failure_unpriv
 84__naked void direct_packet_access_test3(void)
 85{
 86	asm volatile ("					\
 87	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
 88	r0 = 0;						\
 89	exit;						\
 90"	:
 91	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data))
 92	: __clobber_all);
 93}
 94
 95SEC("tc")
 96__description("direct packet access: test4 (write)")
 97__success __retval(0)
 98__naked void direct_packet_access_test4_write(void)
 99{
100	asm volatile ("					\
101	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
102	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
103	r0 = r2;					\
104	r0 += 8;					\
105	if r0 > r3 goto l0_%=;				\
106	*(u8*)(r2 + 0) = r2;				\
107l0_%=:	r0 = 0;						\
108	exit;						\
109"	:
110	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
111	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
112	: __clobber_all);
113}
114
115SEC("tc")
116__description("direct packet access: test5 (pkt_end >= reg, good access)")
117__success __retval(0)
118__naked void pkt_end_reg_good_access(void)
119{
120	asm volatile ("					\
121	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
122	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
123	r0 = r2;					\
124	r0 += 8;					\
125	if r3 >= r0 goto l0_%=;				\
126	r0 = 1;						\
127	exit;						\
128l0_%=:	r0 = *(u8*)(r2 + 0);				\
129	r0 = 0;						\
130	exit;						\
131"	:
132	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
133	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
134	: __clobber_all);
135}
136
137SEC("tc")
138__description("direct packet access: test6 (pkt_end >= reg, bad access)")
139__failure __msg("invalid access to packet")
140__naked void pkt_end_reg_bad_access(void)
141{
142	asm volatile ("					\
143	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
144	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
145	r0 = r2;					\
146	r0 += 8;					\
147	if r3 >= r0 goto l0_%=;				\
148	r0 = *(u8*)(r2 + 0);				\
149	r0 = 1;						\
150	exit;						\
151l0_%=:	r0 = 0;						\
152	exit;						\
153"	:
154	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
155	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
156	: __clobber_all);
157}
158
159SEC("tc")
160__description("direct packet access: test7 (pkt_end >= reg, both accesses)")
161__failure __msg("invalid access to packet")
162__naked void pkt_end_reg_both_accesses(void)
163{
164	asm volatile ("					\
165	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
166	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
167	r0 = r2;					\
168	r0 += 8;					\
169	if r3 >= r0 goto l0_%=;				\
170	r0 = *(u8*)(r2 + 0);				\
171	r0 = 1;						\
172	exit;						\
173l0_%=:	r0 = *(u8*)(r2 + 0);				\
174	r0 = 0;						\
175	exit;						\
176"	:
177	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
178	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
179	: __clobber_all);
180}
181
182SEC("tc")
183__description("direct packet access: test8 (double test, variant 1)")
184__success __retval(0)
185__naked void test8_double_test_variant_1(void)
186{
187	asm volatile ("					\
188	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
189	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
190	r0 = r2;					\
191	r0 += 8;					\
192	if r3 >= r0 goto l0_%=;				\
193	if r0 > r3 goto l1_%=;				\
194	r0 = *(u8*)(r2 + 0);				\
195l1_%=:	r0 = 1;						\
196	exit;						\
197l0_%=:	r0 = *(u8*)(r2 + 0);				\
198	r0 = 0;						\
199	exit;						\
200"	:
201	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
202	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
203	: __clobber_all);
204}
205
206SEC("tc")
207__description("direct packet access: test9 (double test, variant 2)")
208__success __retval(0)
209__naked void test9_double_test_variant_2(void)
210{
211	asm volatile ("					\
212	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
213	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
214	r0 = r2;					\
215	r0 += 8;					\
216	if r3 >= r0 goto l0_%=;				\
217	r0 = 1;						\
218	exit;						\
219l0_%=:	if r0 > r3 goto l1_%=;				\
220	r0 = *(u8*)(r2 + 0);				\
221l1_%=:	r0 = *(u8*)(r2 + 0);				\
222	r0 = 0;						\
223	exit;						\
224"	:
225	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
226	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
227	: __clobber_all);
228}
229
230SEC("tc")
231__description("direct packet access: test10 (write invalid)")
232__failure __msg("invalid access to packet")
233__naked void packet_access_test10_write_invalid(void)
234{
235	asm volatile ("					\
236	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
237	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
238	r0 = r2;					\
239	r0 += 8;					\
240	if r0 > r3 goto l0_%=;				\
241	r0 = 0;						\
242	exit;						\
243l0_%=:	*(u8*)(r2 + 0) = r2;				\
244	r0 = 0;						\
245	exit;						\
246"	:
247	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
248	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
249	: __clobber_all);
250}
251
252SEC("tc")
253__description("direct packet access: test11 (shift, good access)")
254__success __retval(1)
255__naked void access_test11_shift_good_access(void)
256{
257	asm volatile ("					\
258	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
259	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
260	r0 = r2;					\
261	r0 += 22;					\
262	if r0 > r3 goto l0_%=;				\
263	r3 = 144;					\
264	r5 = r3;					\
265	r5 += 23;					\
266	r5 >>= 3;					\
267	r6 = r2;					\
268	r6 += r5;					\
269	r0 = 1;						\
270	exit;						\
271l0_%=:	r0 = 0;						\
272	exit;						\
273"	:
274	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
275	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
276	: __clobber_all);
277}
278
279SEC("tc")
280__description("direct packet access: test12 (and, good access)")
281__success __retval(1)
282__naked void access_test12_and_good_access(void)
283{
284	asm volatile ("					\
285	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
286	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
287	r0 = r2;					\
288	r0 += 22;					\
289	if r0 > r3 goto l0_%=;				\
290	r3 = 144;					\
291	r5 = r3;					\
292	r5 += 23;					\
293	r5 &= 15;					\
294	r6 = r2;					\
295	r6 += r5;					\
296	r0 = 1;						\
297	exit;						\
298l0_%=:	r0 = 0;						\
299	exit;						\
300"	:
301	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
302	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
303	: __clobber_all);
304}
305
306SEC("tc")
307__description("direct packet access: test13 (branches, good access)")
308__success __retval(1)
309__naked void access_test13_branches_good_access(void)
310{
311	asm volatile ("					\
312	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
313	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
314	r0 = r2;					\
315	r0 += 22;					\
316	if r0 > r3 goto l0_%=;				\
317	r3 = *(u32*)(r1 + %[__sk_buff_mark]);		\
318	r4 = 1;						\
319	if r3 > r4 goto l1_%=;				\
320	r3 = 14;					\
321	goto l2_%=;					\
322l1_%=:	r3 = 24;					\
323l2_%=:	r5 = r3;					\
324	r5 += 23;					\
325	r5 &= 15;					\
326	r6 = r2;					\
327	r6 += r5;					\
328	r0 = 1;						\
329	exit;						\
330l0_%=:	r0 = 0;						\
331	exit;						\
332"	:
333	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
334	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),
335	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
336	: __clobber_all);
337}
338
339SEC("tc")
340__description("direct packet access: test14 (pkt_ptr += 0, CONST_IMM, good access)")
341__success __retval(1)
342__naked void _0_const_imm_good_access(void)
343{
344	asm volatile ("					\
345	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
346	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
347	r0 = r2;					\
348	r0 += 22;					\
349	if r0 > r3 goto l0_%=;				\
350	r5 = 12;					\
351	r5 >>= 4;					\
352	r6 = r2;					\
353	r6 += r5;					\
354	r0 = *(u8*)(r6 + 0);				\
355	r0 = 1;						\
356	exit;						\
357l0_%=:	r0 = 0;						\
358	exit;						\
359"	:
360	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
361	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
362	: __clobber_all);
363}
364
365SEC("tc")
366__description("direct packet access: test15 (spill with xadd)")
367__failure __msg("R2 invalid mem access 'scalar'")
368__flag(BPF_F_ANY_ALIGNMENT)
369__naked void access_test15_spill_with_xadd(void)
370{
371	asm volatile ("					\
372	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
373	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
374	r0 = r2;					\
375	r0 += 8;					\
376	if r0 > r3 goto l0_%=;				\
377	r5 = 4096;					\
378	r4 = r10;					\
379	r4 += -8;					\
380	*(u64*)(r4 + 0) = r2;				\
381	lock *(u64 *)(r4 + 0) += r5;			\
382	r2 = *(u64*)(r4 + 0);				\
383	*(u32*)(r2 + 0) = r5;				\
384	r0 = 0;						\
385l0_%=:	exit;						\
386"	:
387	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
388	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
389	: __clobber_all);
390}
391
392SEC("tc")
393__description("direct packet access: test16 (arith on data_end)")
394__failure __msg("R3 pointer arithmetic on pkt_end")
395__naked void test16_arith_on_data_end(void)
396{
397	asm volatile ("					\
398	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
399	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
400	r0 = r2;					\
401	r0 += 8;					\
402	r3 += 16;					\
403	if r0 > r3 goto l0_%=;				\
404	*(u8*)(r2 + 0) = r2;				\
405l0_%=:	r0 = 0;						\
406	exit;						\
407"	:
408	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
409	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
410	: __clobber_all);
411}
412
413SEC("tc")
414__description("direct packet access: test17 (pruning, alignment)")
415__failure __msg("misaligned packet access off 2+0+15+-4 size 4")
416__flag(BPF_F_STRICT_ALIGNMENT)
417__naked void packet_access_test17_pruning_alignment(void)
418{
419	asm volatile ("					\
420	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
421	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
422	r7 = *(u32*)(r1 + %[__sk_buff_mark]);		\
423	r0 = r2;					\
424	r0 += 14;					\
425	if r7 > 1 goto l0_%=;				\
426l2_%=:	if r0 > r3 goto l1_%=;				\
427	*(u32*)(r0 - 4) = r0;				\
428l1_%=:	r0 = 0;						\
429	exit;						\
430l0_%=:	r0 += 1;					\
431	goto l2_%=;					\
432"	:
433	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
434	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),
435	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
436	: __clobber_all);
437}
438
439SEC("tc")
440__description("direct packet access: test18 (imm += pkt_ptr, 1)")
441__success __retval(0)
442__naked void test18_imm_pkt_ptr_1(void)
443{
444	asm volatile ("					\
445	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
446	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
447	r0 = 8;						\
448	r0 += r2;					\
449	if r0 > r3 goto l0_%=;				\
450	*(u8*)(r2 + 0) = r2;				\
451l0_%=:	r0 = 0;						\
452	exit;						\
453"	:
454	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
455	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
456	: __clobber_all);
457}
458
459SEC("tc")
460__description("direct packet access: test19 (imm += pkt_ptr, 2)")
461__success __retval(0)
462__naked void test19_imm_pkt_ptr_2(void)
463{
464	asm volatile ("					\
465	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
466	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
467	r0 = r2;					\
468	r0 += 8;					\
469	if r0 > r3 goto l0_%=;				\
470	r4 = 4;						\
471	r4 += r2;					\
472	*(u8*)(r4 + 0) = r4;				\
473l0_%=:	r0 = 0;						\
474	exit;						\
475"	:
476	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
477	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
478	: __clobber_all);
479}
480
481SEC("tc")
482__description("direct packet access: test20 (x += pkt_ptr, 1)")
483__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
484__naked void test20_x_pkt_ptr_1(void)
485{
486	asm volatile ("					\
487	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
488	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
489	r0 = 0xffffffff;				\
490	*(u64*)(r10 - 8) = r0;				\
491	r0 = *(u64*)(r10 - 8);				\
492	r0 &= 0x7fff;					\
493	r4 = r0;					\
494	r4 += r2;					\
495	r5 = r4;					\
496	r4 += %[__imm_0];				\
497	if r4 > r3 goto l0_%=;				\
498	*(u64*)(r5 + 0) = r4;				\
499l0_%=:	r0 = 0;						\
500	exit;						\
501"	:
502	: __imm_const(__imm_0, 0x7fff - 1),
503	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
504	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
505	: __clobber_all);
506}
507
508SEC("tc")
509__description("direct packet access: test21 (x += pkt_ptr, 2)")
510__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
511__naked void test21_x_pkt_ptr_2(void)
512{
513	asm volatile ("					\
514	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
515	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
516	r0 = r2;					\
517	r0 += 8;					\
518	if r0 > r3 goto l0_%=;				\
519	r4 = 0xffffffff;				\
520	*(u64*)(r10 - 8) = r4;				\
521	r4 = *(u64*)(r10 - 8);				\
522	r4 &= 0x7fff;					\
523	r4 += r2;					\
524	r5 = r4;					\
525	r4 += %[__imm_0];				\
526	if r4 > r3 goto l0_%=;				\
527	*(u64*)(r5 + 0) = r4;				\
528l0_%=:	r0 = 0;						\
529	exit;						\
530"	:
531	: __imm_const(__imm_0, 0x7fff - 1),
532	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
533	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
534	: __clobber_all);
535}
536
537SEC("tc")
538__description("direct packet access: test22 (x += pkt_ptr, 3)")
539__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
540__naked void test22_x_pkt_ptr_3(void)
541{
542	asm volatile ("					\
543	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
544	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
545	r0 = r2;					\
546	r0 += 8;					\
547	*(u64*)(r10 - 8) = r2;				\
548	*(u64*)(r10 - 16) = r3;				\
549	r3 = *(u64*)(r10 - 16);				\
550	if r0 > r3 goto l0_%=;				\
551	r2 = *(u64*)(r10 - 8);				\
552	r4 = 0xffffffff;				\
553	lock *(u64 *)(r10 - 8) += r4;			\
554	r4 = *(u64*)(r10 - 8);				\
555	r4 >>= 49;					\
556	r4 += r2;					\
557	r0 = r4;					\
558	r0 += 2;					\
559	if r0 > r3 goto l0_%=;				\
560	r2 = 1;						\
561	*(u16*)(r4 + 0) = r2;				\
562l0_%=:	r0 = 0;						\
563	exit;						\
564"	:
565	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
566	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
567	: __clobber_all);
568}
569
570SEC("tc")
571__description("direct packet access: test23 (x += pkt_ptr, 4)")
572__failure __msg("invalid access to packet, off=0 size=8, R5(id=3,off=0,r=0)")
573__flag(BPF_F_ANY_ALIGNMENT)
574__naked void test23_x_pkt_ptr_4(void)
575{
576	asm volatile ("					\
577	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
578	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
579	r0 = *(u32*)(r1 + %[__sk_buff_mark]);		\
580	*(u64*)(r10 - 8) = r0;				\
581	r0 = *(u64*)(r10 - 8);				\
582	r0 &= 0xffff;					\
583	r4 = r0;					\
584	r0 = 31;					\
585	r0 += r4;					\
586	r0 += r2;					\
587	r5 = r0;					\
588	r0 += %[__imm_0];				\
589	if r0 > r3 goto l0_%=;				\
590	*(u64*)(r5 + 0) = r0;				\
591l0_%=:	r0 = 0;						\
592	exit;						\
593"	:
594	: __imm_const(__imm_0, 0xffff - 1),
595	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
596	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),
597	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
598	: __clobber_all);
599}
600
601SEC("tc")
602__description("direct packet access: test24 (x += pkt_ptr, 5)")
603__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
604__naked void test24_x_pkt_ptr_5(void)
605{
606	asm volatile ("					\
607	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
608	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
609	r0 = 0xffffffff;				\
610	*(u64*)(r10 - 8) = r0;				\
611	r0 = *(u64*)(r10 - 8);				\
612	r0 &= 0xff;					\
613	r4 = r0;					\
614	r0 = 64;					\
615	r0 += r4;					\
616	r0 += r2;					\
617	r5 = r0;					\
618	r0 += %[__imm_0];				\
619	if r0 > r3 goto l0_%=;				\
620	*(u64*)(r5 + 0) = r0;				\
621l0_%=:	r0 = 0;						\
622	exit;						\
623"	:
624	: __imm_const(__imm_0, 0x7fff - 1),
625	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
626	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
627	: __clobber_all);
628}
629
630SEC("tc")
631__description("direct packet access: test25 (marking on <, good access)")
632__success __retval(0)
633__naked void test25_marking_on_good_access(void)
634{
635	asm volatile ("					\
636	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
637	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
638	r0 = r2;					\
639	r0 += 8;					\
640	if r0 < r3 goto l0_%=;				\
641l1_%=:	r0 = 0;						\
642	exit;						\
643l0_%=:	r0 = *(u8*)(r2 + 0);				\
644	goto l1_%=;					\
645"	:
646	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
647	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
648	: __clobber_all);
649}
650
651SEC("tc")
652__description("direct packet access: test26 (marking on <, bad access)")
653__failure __msg("invalid access to packet")
654__naked void test26_marking_on_bad_access(void)
655{
656	asm volatile ("					\
657	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
658	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
659	r0 = r2;					\
660	r0 += 8;					\
661	if r0 < r3 goto l0_%=;				\
662	r0 = *(u8*)(r2 + 0);				\
663l1_%=:	r0 = 0;						\
664	exit;						\
665l0_%=:	goto l1_%=;					\
666"	:
667	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
668	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
669	: __clobber_all);
670}
671
672SEC("tc")
673__description("direct packet access: test27 (marking on <=, good access)")
674__success __retval(1)
675__naked void test27_marking_on_good_access(void)
676{
677	asm volatile ("					\
678	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
679	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
680	r0 = r2;					\
681	r0 += 8;					\
682	if r3 <= r0 goto l0_%=;				\
683	r0 = *(u8*)(r2 + 0);				\
684l0_%=:	r0 = 1;						\
685	exit;						\
686"	:
687	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
688	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
689	: __clobber_all);
690}
691
692SEC("tc")
693__description("direct packet access: test28 (marking on <=, bad access)")
694__failure __msg("invalid access to packet")
695__naked void test28_marking_on_bad_access(void)
696{
697	asm volatile ("					\
698	r2 = *(u32*)(r1 + %[__sk_buff_data]);		\
699	r3 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
700	r0 = r2;					\
701	r0 += 8;					\
702	if r3 <= r0 goto l0_%=;				\
703l1_%=:	r0 = 1;						\
704	exit;						\
705l0_%=:	r0 = *(u8*)(r2 + 0);				\
706	goto l1_%=;					\
707"	:
708	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
709	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
710	: __clobber_all);
711}
712
713SEC("tc")
714__description("direct packet access: test29 (reg > pkt_end in subprog)")
715__success __retval(0)
716__naked void reg_pkt_end_in_subprog(void)
717{
718	asm volatile ("					\
719	r6 = *(u32*)(r1 + %[__sk_buff_data]);		\
720	r2 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
721	r3 = r6;					\
722	r3 += 8;					\
723	call reg_pkt_end_in_subprog__1;			\
724	if r0 == 0 goto l0_%=;				\
725	r0 = *(u8*)(r6 + 0);				\
726l0_%=:	r0 = 0;						\
727	exit;						\
728"	:
729	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
730	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
731	: __clobber_all);
732}
733
734static __naked __noinline __attribute__((used))
735void reg_pkt_end_in_subprog__1(void)
736{
737	asm volatile ("					\
738	r0 = 0;						\
739	if r3 > r2 goto l0_%=;				\
740	r0 = 1;						\
741l0_%=:	exit;						\
742"	::: __clobber_all);
743}
744
745SEC("tc")
746__description("direct packet access: test30 (check_id() in regsafe(), bad access)")
747__failure __msg("invalid access to packet, off=0 size=1, R2")
748__flag(BPF_F_TEST_STATE_FREQ)
749__naked void id_in_regsafe_bad_access(void)
750{
751	asm volatile ("					\
752	/* r9 = ctx */					\
753	r9 = r1;					\
754	/* r7 = ktime_get_ns() */			\
755	call %[bpf_ktime_get_ns];			\
756	r7 = r0;					\
757	/* r6 = ktime_get_ns() */			\
758	call %[bpf_ktime_get_ns];			\
759	r6 = r0;					\
760	/* r2 = ctx->data				\
761	 * r3 = ctx->data				\
762	 * r4 = ctx->data_end				\
763	 */						\
764	r2 = *(u32*)(r9 + %[__sk_buff_data]);		\
765	r3 = *(u32*)(r9 + %[__sk_buff_data]);		\
766	r4 = *(u32*)(r9 + %[__sk_buff_data_end]);	\
767	/* if r6 > 100 goto exit			\
768	 * if r7 > 100 goto exit			\
769	 */						\
770	if r6 > 100 goto l0_%=;				\
771	if r7 > 100 goto l0_%=;				\
772	/* r2 += r6              ; this forces assignment of ID to r2\
773	 * r2 += 1               ; get some fixed off for r2\
774	 * r3 += r7              ; this forces assignment of ID to r3\
775	 * r3 += 1               ; get some fixed off for r3\
776	 */						\
777	r2 += r6;					\
778	r2 += 1;					\
779	r3 += r7;					\
780	r3 += 1;					\
781	/* if r6 > r7 goto +1    ; no new information about the state is derived from\
782	 *                       ; this check, thus produced verifier states differ\
783	 *                       ; only in 'insn_idx'	\
784	 * r2 = r3               ; optionally share ID between r2 and r3\
785	 */						\
786	if r6 != r7 goto l1_%=;				\
787	r2 = r3;					\
788l1_%=:	/* if r3 > ctx->data_end goto exit */		\
789	if r3 > r4 goto l0_%=;				\
790	/* r5 = *(u8 *) (r2 - 1) ; access packet memory using r2,\
791	 *                       ; this is not always safe\
792	 */						\
793	r5 = *(u8*)(r2 - 1);				\
794l0_%=:	/* exit(0) */					\
795	r0 = 0;						\
796	exit;						\
797"	:
798	: __imm(bpf_ktime_get_ns),
799	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
800	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
801	: __clobber_all);
802}
803
804#define access_test_non_linear(name, type, desc, retval, linear_sz, off)			\
805	SEC(type)										\
806	__description("direct packet access: " #name " (non-linear, " type ", " desc ")")	\
807	__success __retval(retval)								\
808	__linear_size(linear_sz)								\
809	__naked void access_non_linear_##name(void)						\
810	{											\
811		asm volatile ("									\
812		r2 = *(u32*)(r1 + %[skb_data]);							\
813		r3 = *(u32*)(r1 + %[skb_data_end]);						\
814		r0 = r2;									\
815		r0 += %[offset];								\
816		if r0 > r3 goto l0_%=;								\
817		r0 = *(u8*)(r0 - 1);								\
818		r0 = 0;										\
819		exit;										\
820	l0_%=:	r0 = 1;										\
821		exit;										\
822	"	:										\
823		: __imm_const(skb_data, offsetof(struct __sk_buff, data)),			\
824		  __imm_const(skb_data_end, offsetof(struct __sk_buff, data_end)),		\
825		  __imm_const(offset, off)							\
826		: __clobber_all);								\
827	}
828
829access_test_non_linear(test31, "tc", "too short eth", 1, ETH_HLEN, 22);
830access_test_non_linear(test32, "tc", "too short 1", 1, 1, 22);
831access_test_non_linear(test33, "tc", "long enough", 0, 22, 22);
832access_test_non_linear(test34, "cgroup_skb/ingress", "too short eth", 1, ETH_HLEN, 8);
833access_test_non_linear(test35, "cgroup_skb/ingress", "too short 1", 1, 1, 8);
834access_test_non_linear(test36, "cgroup_skb/ingress", "long enough", 0, 22, 8);
835
836SEC("tc")
837__description("direct packet access: test37 (non-linear, linearized)")
838__success __retval(0)
839__linear_size(ETH_HLEN)
840__naked void access_non_linear_linearized(void)
841{
842	asm volatile ("				\
843	r6 = r1;				\
844	r2 = 22;				\
845	call %[bpf_skb_pull_data];		\
846	r2 = *(u32*)(r6 + %[skb_data]);		\
847	r3 = *(u32*)(r6 + %[skb_data_end]);	\
848	r0 = r2;				\
849	r0 += 22;				\
850	if r0 > r3 goto l0_%=;			\
851	r0 = *(u8*)(r0 - 1);			\
852	exit;					\
853l0_%=:	r0 = 1;					\
854	exit;					\
855"	:
856	: __imm(bpf_skb_pull_data),
857	  __imm_const(skb_data, offsetof(struct __sk_buff, data)),
858	  __imm_const(skb_data_end, offsetof(struct __sk_buff, data_end))
859	: __clobber_all);
860}
861
862char _license[] SEC("license") = "GPL";
~/ Read-only file preview.