xref: /linux/tools/testing/selftests/bpf/progs/verifier_value_illegal_alu.c (revision cbf33b8e0b360f667b17106c15d9e2aac77a76a1)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/value_illegal_alu.c */
3 
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include "../../../include/linux/filter.h"
7 #include "bpf_misc.h"
8 
9 #define MAX_ENTRIES 11
10 
11 struct test_val {
12 	unsigned int index;
13 	int foo[MAX_ENTRIES];
14 };
15 
16 struct {
17 	__uint(type, BPF_MAP_TYPE_HASH);
18 	__uint(max_entries, 1);
19 	__type(key, long long);
20 	__type(value, struct test_val);
21 } map_hash_48b SEC(".maps");
22 
23 SEC("socket")
24 __description("map element value illegal alu op, 1")
25 __failure __msg("R0 bitwise operator &= on pointer")
26 __failure_unpriv
27 __naked void value_illegal_alu_op_1(void)
28 {
29 	asm volatile ("					\
30 	r2 = r10;					\
31 	r2 += -8;					\
32 	r1 = 0;						\
33 	*(u64*)(r2 + 0) = r1;				\
34 	r1 = %[map_hash_48b] ll;			\
35 	call %[bpf_map_lookup_elem];			\
36 	if r0 == 0 goto l0_%=;				\
37 	r0 &= 8;					\
38 	r1 = 22;					\
39 	*(u64*)(r0 + 0) = r1;				\
40 l0_%=:	exit;						\
41 "	:
42 	: __imm(bpf_map_lookup_elem),
43 	  __imm_addr(map_hash_48b)
44 	: __clobber_all);
45 }
46 
47 SEC("socket")
48 __description("map element value illegal alu op, 2")
49 __failure __msg("R0 32-bit pointer arithmetic prohibited")
50 __failure_unpriv
51 __naked void value_illegal_alu_op_2(void)
52 {
53 	asm volatile ("					\
54 	r2 = r10;					\
55 	r2 += -8;					\
56 	r1 = 0;						\
57 	*(u64*)(r2 + 0) = r1;				\
58 	r1 = %[map_hash_48b] ll;			\
59 	call %[bpf_map_lookup_elem];			\
60 	if r0 == 0 goto l0_%=;				\
61 	w0 += 0;					\
62 	r1 = 22;					\
63 	*(u64*)(r0 + 0) = r1;				\
64 l0_%=:	exit;						\
65 "	:
66 	: __imm(bpf_map_lookup_elem),
67 	  __imm_addr(map_hash_48b)
68 	: __clobber_all);
69 }
70 
71 SEC("socket")
72 __description("map element value illegal alu op, 3")
73 __failure __msg("R0 pointer arithmetic with /= operator")
74 __failure_unpriv
75 __naked void value_illegal_alu_op_3(void)
76 {
77 	asm volatile ("					\
78 	r2 = r10;					\
79 	r2 += -8;					\
80 	r1 = 0;						\
81 	*(u64*)(r2 + 0) = r1;				\
82 	r1 = %[map_hash_48b] ll;			\
83 	call %[bpf_map_lookup_elem];			\
84 	if r0 == 0 goto l0_%=;				\
85 	r0 /= 42;					\
86 	r1 = 22;					\
87 	*(u64*)(r0 + 0) = r1;				\
88 l0_%=:	exit;						\
89 "	:
90 	: __imm(bpf_map_lookup_elem),
91 	  __imm_addr(map_hash_48b)
92 	: __clobber_all);
93 }
94 
95 SEC("socket")
96 __description("map element value illegal alu op, 4")
97 __failure __msg("invalid mem access 'scalar'")
98 __failure_unpriv __msg_unpriv("R0 pointer arithmetic prohibited")
99 __flag(BPF_F_ANY_ALIGNMENT)
100 __naked void value_illegal_alu_op_4(void)
101 {
102 	asm volatile ("					\
103 	r2 = r10;					\
104 	r2 += -8;					\
105 	r1 = 0;						\
106 	*(u64*)(r2 + 0) = r1;				\
107 	r1 = %[map_hash_48b] ll;			\
108 	call %[bpf_map_lookup_elem];			\
109 	if r0 == 0 goto l0_%=;				\
110 	r0 = be64 r0;					\
111 	r1 = 22;					\
112 	*(u64*)(r0 + 0) = r1;				\
113 l0_%=:	exit;						\
114 "	:
115 	: __imm(bpf_map_lookup_elem),
116 	  __imm_addr(map_hash_48b)
117 	: __clobber_all);
118 }
119 
120 SEC("socket")
121 __description("map element value illegal alu op, 5")
122 __failure __msg("R0 invalid mem access 'scalar'")
123 __msg_unpriv("leaking pointer from stack off -8")
124 __flag(BPF_F_ANY_ALIGNMENT)
125 __naked void value_illegal_alu_op_5(void)
126 {
127 	asm volatile ("					\
128 	r2 = r10;					\
129 	r2 += -8;					\
130 	r1 = 0;						\
131 	*(u64*)(r2 + 0) = r1;				\
132 	r1 = %[map_hash_48b] ll;			\
133 	call %[bpf_map_lookup_elem];			\
134 	if r0 == 0 goto l0_%=;				\
135 	r3 = 4096;					\
136 	r2 = r10;					\
137 	r2 += -8;					\
138 	*(u64*)(r2 + 0) = r0;				\
139 	lock *(u64 *)(r2 + 0) += r3;			\
140 	r0 = *(u64*)(r2 + 0);				\
141 	r1 = 22;					\
142 	*(u64*)(r0 + 0) = r1;				\
143 l0_%=:	exit;						\
144 "	:
145 	: __imm(bpf_map_lookup_elem),
146 	  __imm_addr(map_hash_48b)
147 	: __clobber_all);
148 }
149 
150 SEC("socket")
151 __description("map_ptr illegal alu op, map_ptr = -map_ptr")
152 __failure __msg("R0 invalid mem access 'scalar'")
153 __failure_unpriv __msg_unpriv("R0 pointer arithmetic prohibited")
154 __flag(BPF_F_ANY_ALIGNMENT)
155 __naked void map_ptr_illegal_alu_op(void)
156 {
157 	asm volatile ("					\
158 	r0 = %[map_hash_48b] ll;			\
159 	r0 = -r0;					\
160 	r1 = 22;					\
161 	*(u64*)(r0 + 0) = r1;				\
162 	exit;						\
163 "	:
164 	: __imm_addr(map_hash_48b)
165 	: __clobber_all);
166 }
167 
168 SEC("flow_dissector")
169 __description("flow_keys illegal alu op with variable offset")
170 __failure __msg("R7 pointer arithmetic on flow_keys prohibited")
171 __naked void flow_keys_illegal_variable_offset_alu(void)
172 {
173 	asm volatile("					\
174 	r6 = r1;					\
175 	r7 = *(u64*)(r6 + %[flow_keys_off]);		\
176 	r8 = 8;						\
177 	r8 /= 1;					\
178 	r8 &= 8;					\
179 	r7 += r8;					\
180 	r0 = *(u64*)(r7 + 0);				\
181 	exit;						\
182 "	:
183 	: __imm_const(flow_keys_off, offsetof(struct __sk_buff, flow_keys))
184 	: __clobber_all);
185 }
186 
187 #define DEFINE_BAD_OFFSET_TEST(name, op, off, imm)	\
188 	SEC("socket")					\
189 	__failure __msg("BPF_ALU uses reserved fields") \
190 	__naked void name(void)				\
191 	{						\
192 		asm volatile(				\
193 			"r0 = 1;"			\
194 			".8byte %[insn];"		\
195 			"r0 = 0;"			\
196 			"exit;"				\
197 		:					\
198 		: __imm_insn(insn, BPF_RAW_INSN((op), 0, 0, (off), (imm))) \
199 		: __clobber_all);			\
200 	}
201 
202 /*
203  * Offset fields of 0 and 1 are legal for BPF_{DIV,MOD} instructions.
204  * Offset fields of 0 are legal for the rest of ALU instructions.
205  * Test that error is reported for illegal offsets, assuming that tests
206  * for legal offsets exist.
207  */
208 DEFINE_BAD_OFFSET_TEST(bad_offset_divx, BPF_ALU64 | BPF_DIV | BPF_X, -1, 0)
209 DEFINE_BAD_OFFSET_TEST(bad_offset_modk, BPF_ALU64 | BPF_MOD | BPF_K, -1, 1)
210 DEFINE_BAD_OFFSET_TEST(bad_offset_addx, BPF_ALU64 | BPF_ADD | BPF_X, -1, 0)
211 DEFINE_BAD_OFFSET_TEST(bad_offset_divx2, BPF_ALU64 | BPF_DIV | BPF_X, 2, 0)
212 DEFINE_BAD_OFFSET_TEST(bad_offset_modk2, BPF_ALU64 | BPF_MOD | BPF_K, 2, 1)
213 DEFINE_BAD_OFFSET_TEST(bad_offset_addx2, BPF_ALU64 | BPF_ADD | BPF_X, 1, 0)
214 
215 char _license[] SEC("license") = "GPL";
216