xref: /linux/tools/testing/selftests/bpf/progs/verifier_flow_keys.c (revision 68f4e480b089abae26fbab0c38c3df3cbac3d79d)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Bounds checks for PTR_TO_FLOW_KEYS pointer arithmetic. */
3 
4 #include "vmlinux.h"
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7 
8 /* sizeof(struct bpf_flow_keys) is well under 4096, so +0x1000 is OOB. */
9 
10 SEC("flow_dissector")
11 __description("flow_keys: in-bounds constant pointer arithmetic accepted")
12 __success
13 __naked void flow_keys_const_inbounds(void)
14 {
15 	asm volatile ("					\
16 	r1 = *(u64 *)(r1 + %[flow_keys]);		\
17 	r1 += 8;					\
18 	r0 = *(u64 *)(r1 + 0);				\
19 	r0 = 0;						\
20 	exit;						\
21 "	:
22 	: __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys))
23 	: __clobber_all);
24 }
25 
26 SEC("flow_dissector")
27 __description("flow_keys: OOB via constant pointer arithmetic rejected")
28 __failure __msg("invalid access to flow keys off=4096 size=8")
29 __naked void flow_keys_const_oob_read(void)
30 {
31 	asm volatile ("					\
32 	r1 = *(u64 *)(r1 + %[flow_keys]);		\
33 	r1 += 4096;					\
34 	r0 = *(u64 *)(r1 + 0);				\
35 	r0 = 0;						\
36 	exit;						\
37 "	:
38 	: __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys))
39 	: __clobber_all);
40 }
41 
42 SEC("flow_dissector")
43 __description("flow_keys: OOB write via constant pointer arithmetic rejected")
44 __failure __msg("invalid access to flow keys off=4096 size=8")
45 __naked void flow_keys_const_oob_write(void)
46 {
47 	asm volatile ("					\
48 	r1 = *(u64 *)(r1 + %[flow_keys]);		\
49 	r1 += 4096;					\
50 	r2 = 0;						\
51 	*(u64 *)(r1 + 0) = r2;				\
52 	r0 = 0;						\
53 	exit;						\
54 "	:
55 	: __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys))
56 	: __clobber_all);
57 }
58 
59 /* Equivalent OOB expressed directly in insn->off; this form was always
60  * rejected and is kept to show both forms now share one diagnostic.
61  */
62 SEC("flow_dissector")
63 __description("flow_keys: OOB via insn->off rejected")
64 __failure __msg("invalid access to flow keys off=4096 size=8")
65 __naked void flow_keys_insn_off_oob(void)
66 {
67 	asm volatile ("					\
68 	r1 = *(u64 *)(r1 + %[flow_keys]);		\
69 	r0 = *(u64 *)(r1 + 4096);			\
70 	r0 = 0;						\
71 	exit;						\
72 "	:
73 	: __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys))
74 	: __clobber_all);
75 }
76 
77 SEC("flow_dissector")
78 __description("flow_keys: variable pointer arithmetic rejected")
79 __failure __msg("R1 pointer arithmetic on flow_keys prohibited")
80 __naked void flow_keys_var_read(void)
81 {
82 	asm volatile ("					\
83 	r6 = r1;					\
84 	call %[bpf_get_prandom_u32];			\
85 	r0 &= 0xFFFF;					\
86 	r1 = *(u64 *)(r6 + %[flow_keys]);		\
87 	r1 += r0;					\
88 	r0 = *(u64 *)(r1 + 0);				\
89 	r0 = 0;						\
90 	exit;						\
91 "	:
92 	: __imm_const(flow_keys, offsetof(struct __sk_buff, flow_keys)),
93 	  __imm(bpf_get_prandom_u32)
94 	: __clobber_all);
95 }
96 
97 char _license[] SEC("license") = "GPL";
98