]> git.ipfire.org Git - thirdparty/linux.git/blob - tools/testing/selftests/bpf/verifier/bounds.c
Merge tag 'drm/tegra/for-5.7-fixes' of git://anongit.freedesktop.org/tegra/linux...
[thirdparty/linux.git] / tools / testing / selftests / bpf / verifier / bounds.c
1 {
2 "subtraction bounds (map value) variant 1",
3 .insns = {
4 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7 BPF_LD_MAP_FD(BPF_REG_1, 0),
8 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
9 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
10 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
11 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 7),
12 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
13 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 5),
14 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
15 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 56),
16 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
17 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
18 BPF_EXIT_INSN(),
19 BPF_MOV64_IMM(BPF_REG_0, 0),
20 BPF_EXIT_INSN(),
21 },
22 .fixup_map_hash_8b = { 3 },
23 .errstr = "R0 max value is outside of the array range",
24 .result = REJECT,
25 },
26 {
27 "subtraction bounds (map value) variant 2",
28 .insns = {
29 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
30 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
31 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
32 BPF_LD_MAP_FD(BPF_REG_1, 0),
33 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
34 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
35 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
36 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 6),
37 BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
38 BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 4),
39 BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
40 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
41 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
42 BPF_EXIT_INSN(),
43 BPF_MOV64_IMM(BPF_REG_0, 0),
44 BPF_EXIT_INSN(),
45 },
46 .fixup_map_hash_8b = { 3 },
47 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
48 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
49 .result = REJECT,
50 },
51 {
52 "check subtraction on pointers for unpriv",
53 .insns = {
54 BPF_MOV64_IMM(BPF_REG_0, 0),
55 BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
56 BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
57 BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
58 BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 9),
59 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
60 BPF_MOV64_REG(BPF_REG_9, BPF_REG_FP),
61 BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_0),
62 BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
63 BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
64 BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
65 BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 0),
66 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
67 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
68 BPF_EXIT_INSN(),
69 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_9, 0),
70 BPF_MOV64_IMM(BPF_REG_0, 0),
71 BPF_EXIT_INSN(),
72 },
73 .fixup_map_hash_8b = { 1, 9 },
74 .result = ACCEPT,
75 .result_unpriv = REJECT,
76 .errstr_unpriv = "R9 pointer -= pointer prohibited",
77 },
78 {
79 "bounds check based on zero-extended MOV",
80 .insns = {
81 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
82 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
83 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
84 BPF_LD_MAP_FD(BPF_REG_1, 0),
85 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
86 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
87 /* r2 = 0x0000'0000'ffff'ffff */
88 BPF_MOV32_IMM(BPF_REG_2, 0xffffffff),
89 /* r2 = 0 */
90 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 32),
91 /* no-op */
92 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
93 /* access at offset 0 */
94 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
95 /* exit */
96 BPF_MOV64_IMM(BPF_REG_0, 0),
97 BPF_EXIT_INSN(),
98 },
99 .fixup_map_hash_8b = { 3 },
100 .result = ACCEPT
101 },
102 {
103 "bounds check based on sign-extended MOV. test1",
104 .insns = {
105 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
106 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
107 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
108 BPF_LD_MAP_FD(BPF_REG_1, 0),
109 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
110 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
111 /* r2 = 0xffff'ffff'ffff'ffff */
112 BPF_MOV64_IMM(BPF_REG_2, 0xffffffff),
113 /* r2 = 0xffff'ffff */
114 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 32),
115 /* r0 = <oob pointer> */
116 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
117 /* access to OOB pointer */
118 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
119 /* exit */
120 BPF_MOV64_IMM(BPF_REG_0, 0),
121 BPF_EXIT_INSN(),
122 },
123 .fixup_map_hash_8b = { 3 },
124 .errstr = "map_value pointer and 4294967295",
125 .result = REJECT
126 },
127 {
128 "bounds check based on sign-extended MOV. test2",
129 .insns = {
130 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
131 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
132 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
133 BPF_LD_MAP_FD(BPF_REG_1, 0),
134 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
135 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
136 /* r2 = 0xffff'ffff'ffff'ffff */
137 BPF_MOV64_IMM(BPF_REG_2, 0xffffffff),
138 /* r2 = 0xfff'ffff */
139 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 36),
140 /* r0 = <oob pointer> */
141 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
142 /* access to OOB pointer */
143 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
144 /* exit */
145 BPF_MOV64_IMM(BPF_REG_0, 0),
146 BPF_EXIT_INSN(),
147 },
148 .fixup_map_hash_8b = { 3 },
149 .errstr = "R0 min value is outside of the array range",
150 .result = REJECT
151 },
152 {
153 "bounds check based on reg_off + var_off + insn_off. test1",
154 .insns = {
155 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
156 offsetof(struct __sk_buff, mark)),
157 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
158 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
159 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
160 BPF_LD_MAP_FD(BPF_REG_1, 0),
161 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
162 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
163 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 1),
164 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, (1 << 29) - 1),
165 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_6),
166 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, (1 << 29) - 1),
167 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 3),
168 BPF_MOV64_IMM(BPF_REG_0, 0),
169 BPF_EXIT_INSN(),
170 },
171 .fixup_map_hash_8b = { 4 },
172 .errstr = "value_size=8 off=1073741825",
173 .result = REJECT,
174 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
175 },
176 {
177 "bounds check based on reg_off + var_off + insn_off. test2",
178 .insns = {
179 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
180 offsetof(struct __sk_buff, mark)),
181 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
182 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
183 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
184 BPF_LD_MAP_FD(BPF_REG_1, 0),
185 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
186 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
187 BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 1),
188 BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, (1 << 30) - 1),
189 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_6),
190 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, (1 << 29) - 1),
191 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 3),
192 BPF_MOV64_IMM(BPF_REG_0, 0),
193 BPF_EXIT_INSN(),
194 },
195 .fixup_map_hash_8b = { 4 },
196 .errstr = "value 1073741823",
197 .result = REJECT,
198 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
199 },
200 {
201 "bounds check after truncation of non-boundary-crossing range",
202 .insns = {
203 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
204 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
205 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
206 BPF_LD_MAP_FD(BPF_REG_1, 0),
207 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
208 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
209 /* r1 = [0x00, 0xff] */
210 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
211 BPF_MOV64_IMM(BPF_REG_2, 1),
212 /* r2 = 0x10'0000'0000 */
213 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 36),
214 /* r1 = [0x10'0000'0000, 0x10'0000'00ff] */
215 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
216 /* r1 = [0x10'7fff'ffff, 0x10'8000'00fe] */
217 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
218 /* r1 = [0x00, 0xff] */
219 BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 0x7fffffff),
220 /* r1 = 0 */
221 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
222 /* no-op */
223 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
224 /* access at offset 0 */
225 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
226 /* exit */
227 BPF_MOV64_IMM(BPF_REG_0, 0),
228 BPF_EXIT_INSN(),
229 },
230 .fixup_map_hash_8b = { 3 },
231 .result = ACCEPT
232 },
233 {
234 "bounds check after truncation of boundary-crossing range (1)",
235 .insns = {
236 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
237 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
238 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
239 BPF_LD_MAP_FD(BPF_REG_1, 0),
240 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
241 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
242 /* r1 = [0x00, 0xff] */
243 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
244 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
245 /* r1 = [0xffff'ff80, 0x1'0000'007f] */
246 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
247 /* r1 = [0xffff'ff80, 0xffff'ffff] or
248 * [0x0000'0000, 0x0000'007f]
249 */
250 BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 0),
251 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
252 /* r1 = [0x00, 0xff] or
253 * [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
254 */
255 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
256 /* r1 = 0 or
257 * [0x00ff'ffff'ff00'0000, 0x00ff'ffff'ffff'ffff]
258 */
259 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
260 /* error on OOB pointer computation */
261 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
262 /* exit */
263 BPF_MOV64_IMM(BPF_REG_0, 0),
264 BPF_EXIT_INSN(),
265 },
266 .fixup_map_hash_8b = { 3 },
267 /* not actually fully unbounded, but the bound is very high */
268 .errstr = "value 72057594021150720 makes map_value pointer be out of bounds",
269 .result = REJECT
270 },
271 {
272 "bounds check after truncation of boundary-crossing range (2)",
273 .insns = {
274 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
275 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
276 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
277 BPF_LD_MAP_FD(BPF_REG_1, 0),
278 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
279 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
280 /* r1 = [0x00, 0xff] */
281 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
282 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
283 /* r1 = [0xffff'ff80, 0x1'0000'007f] */
284 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
285 /* r1 = [0xffff'ff80, 0xffff'ffff] or
286 * [0x0000'0000, 0x0000'007f]
287 * difference to previous test: truncation via MOV32
288 * instead of ALU32.
289 */
290 BPF_MOV32_REG(BPF_REG_1, BPF_REG_1),
291 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
292 /* r1 = [0x00, 0xff] or
293 * [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
294 */
295 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
296 /* r1 = 0 or
297 * [0x00ff'ffff'ff00'0000, 0x00ff'ffff'ffff'ffff]
298 */
299 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
300 /* error on OOB pointer computation */
301 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
302 /* exit */
303 BPF_MOV64_IMM(BPF_REG_0, 0),
304 BPF_EXIT_INSN(),
305 },
306 .fixup_map_hash_8b = { 3 },
307 /* not actually fully unbounded, but the bound is very high */
308 .errstr = "value 72057594021150720 makes map_value pointer be out of bounds",
309 .result = REJECT
310 },
311 {
312 "bounds check after wrapping 32-bit addition",
313 .insns = {
314 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
315 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
316 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
317 BPF_LD_MAP_FD(BPF_REG_1, 0),
318 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
319 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
320 /* r1 = 0x7fff'ffff */
321 BPF_MOV64_IMM(BPF_REG_1, 0x7fffffff),
322 /* r1 = 0xffff'fffe */
323 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
324 /* r1 = 0 */
325 BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 2),
326 /* no-op */
327 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
328 /* access at offset 0 */
329 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
330 /* exit */
331 BPF_MOV64_IMM(BPF_REG_0, 0),
332 BPF_EXIT_INSN(),
333 },
334 .fixup_map_hash_8b = { 3 },
335 .result = ACCEPT
336 },
337 {
338 "bounds check after shift with oversized count operand",
339 .insns = {
340 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
341 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
342 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
343 BPF_LD_MAP_FD(BPF_REG_1, 0),
344 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
345 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
346 BPF_MOV64_IMM(BPF_REG_2, 32),
347 BPF_MOV64_IMM(BPF_REG_1, 1),
348 /* r1 = (u32)1 << (u32)32 = ? */
349 BPF_ALU32_REG(BPF_LSH, BPF_REG_1, BPF_REG_2),
350 /* r1 = [0x0000, 0xffff] */
351 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xffff),
352 /* computes unknown pointer, potentially OOB */
353 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
354 /* potentially OOB access */
355 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
356 /* exit */
357 BPF_MOV64_IMM(BPF_REG_0, 0),
358 BPF_EXIT_INSN(),
359 },
360 .fixup_map_hash_8b = { 3 },
361 .errstr = "R0 max value is outside of the array range",
362 .result = REJECT
363 },
364 {
365 "bounds check after right shift of maybe-negative number",
366 .insns = {
367 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
368 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
369 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
370 BPF_LD_MAP_FD(BPF_REG_1, 0),
371 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
372 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
373 /* r1 = [0x00, 0xff] */
374 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
375 /* r1 = [-0x01, 0xfe] */
376 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
377 /* r1 = 0 or 0xff'ffff'ffff'ffff */
378 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
379 /* r1 = 0 or 0xffff'ffff'ffff */
380 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
381 /* computes unknown pointer, potentially OOB */
382 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
383 /* potentially OOB access */
384 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
385 /* exit */
386 BPF_MOV64_IMM(BPF_REG_0, 0),
387 BPF_EXIT_INSN(),
388 },
389 .fixup_map_hash_8b = { 3 },
390 .errstr = "R0 unbounded memory access",
391 .result = REJECT
392 },
393 {
394 "bounds check after 32-bit right shift with 64-bit input",
395 .insns = {
396 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
397 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
398 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
399 BPF_LD_MAP_FD(BPF_REG_1, 0),
400 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
401 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
402 /* r1 = 2 */
403 BPF_MOV64_IMM(BPF_REG_1, 2),
404 /* r1 = 1<<32 */
405 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31),
406 /* r1 = 0 (NOT 2!) */
407 BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31),
408 /* r1 = 0xffff'fffe (NOT 0!) */
409 BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2),
410 /* error on computing OOB pointer */
411 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
412 /* exit */
413 BPF_MOV64_IMM(BPF_REG_0, 0),
414 BPF_EXIT_INSN(),
415 },
416 .fixup_map_hash_8b = { 3 },
417 .errstr = "math between map_value pointer and 4294967294 is not allowed",
418 .result = REJECT,
419 },
420 {
421 "bounds check map access with off+size signed 32bit overflow. test1",
422 .insns = {
423 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
424 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
425 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
426 BPF_LD_MAP_FD(BPF_REG_1, 0),
427 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
428 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
429 BPF_EXIT_INSN(),
430 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe),
431 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
432 BPF_JMP_A(0),
433 BPF_EXIT_INSN(),
434 },
435 .fixup_map_hash_8b = { 3 },
436 .errstr = "map_value pointer and 2147483646",
437 .result = REJECT
438 },
439 {
440 "bounds check map access with off+size signed 32bit overflow. test2",
441 .insns = {
442 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
443 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
444 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
445 BPF_LD_MAP_FD(BPF_REG_1, 0),
446 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
447 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
448 BPF_EXIT_INSN(),
449 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
450 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
451 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
452 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
453 BPF_JMP_A(0),
454 BPF_EXIT_INSN(),
455 },
456 .fixup_map_hash_8b = { 3 },
457 .errstr = "pointer offset 1073741822",
458 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
459 .result = REJECT
460 },
461 {
462 "bounds check map access with off+size signed 32bit overflow. test3",
463 .insns = {
464 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
465 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
466 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
467 BPF_LD_MAP_FD(BPF_REG_1, 0),
468 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
469 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
470 BPF_EXIT_INSN(),
471 BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
472 BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
473 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
474 BPF_JMP_A(0),
475 BPF_EXIT_INSN(),
476 },
477 .fixup_map_hash_8b = { 3 },
478 .errstr = "pointer offset -1073741822",
479 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
480 .result = REJECT
481 },
482 {
483 "bounds check map access with off+size signed 32bit overflow. test4",
484 .insns = {
485 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
486 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
487 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
488 BPF_LD_MAP_FD(BPF_REG_1, 0),
489 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
490 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
491 BPF_EXIT_INSN(),
492 BPF_MOV64_IMM(BPF_REG_1, 1000000),
493 BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000),
494 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
495 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
496 BPF_JMP_A(0),
497 BPF_EXIT_INSN(),
498 },
499 .fixup_map_hash_8b = { 3 },
500 .errstr = "map_value pointer and 1000000000000",
501 .result = REJECT
502 },
503 {
504 "bounds check mixed 32bit and 64bit arithmetic. test1",
505 .insns = {
506 BPF_MOV64_IMM(BPF_REG_0, 0),
507 BPF_MOV64_IMM(BPF_REG_1, -1),
508 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
509 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
510 /* r1 = 0xffffFFFF00000001 */
511 BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 1, 3),
512 /* check ALU64 op keeps 32bit bounds */
513 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
514 BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 2, 1),
515 BPF_JMP_A(1),
516 /* invalid ldx if bounds are lost above */
517 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
518 BPF_EXIT_INSN(),
519 },
520 .result = ACCEPT
521 },
522 {
523 "bounds check mixed 32bit and 64bit arithmetic. test2",
524 .insns = {
525 BPF_MOV64_IMM(BPF_REG_0, 0),
526 BPF_MOV64_IMM(BPF_REG_1, -1),
527 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
528 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
529 /* r1 = 0xffffFFFF00000001 */
530 BPF_MOV64_IMM(BPF_REG_2, 3),
531 /* r1 = 0x2 */
532 BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
533 /* check ALU32 op zero extends 64bit bounds */
534 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1),
535 BPF_JMP_A(1),
536 /* invalid ldx if bounds are lost above */
537 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
538 BPF_EXIT_INSN(),
539 },
540 .result = ACCEPT
541 },