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 allowed memory 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 allowed memory 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, 8),
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 	/* error on OOB pointer computation */
257 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
258 	/* exit */
259 	BPF_MOV64_IMM(BPF_REG_0, 0),
260 	BPF_EXIT_INSN(),
261 	},
262 	.fixup_map_hash_8b = { 3 },
263 	/* not actually fully unbounded, but the bound is very high */
264 	.errstr = "value -4294967168 makes map_value pointer be out of bounds",
265 	.result = REJECT,
266 },
267 {
268 	"bounds check after truncation of boundary-crossing range (2)",
269 	.insns = {
270 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
271 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
272 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
273 	BPF_LD_MAP_FD(BPF_REG_1, 0),
274 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
275 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
276 	/* r1 = [0x00, 0xff] */
277 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
278 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
279 	/* r1 = [0xffff'ff80, 0x1'0000'007f] */
280 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
281 	/* r1 = [0xffff'ff80, 0xffff'ffff] or
282 	 *      [0x0000'0000, 0x0000'007f]
283 	 * difference to previous test: truncation via MOV32
284 	 * instead of ALU32.
285 	 */
286 	BPF_MOV32_REG(BPF_REG_1, BPF_REG_1),
287 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
288 	/* r1 = [0x00, 0xff] or
289 	 *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
290 	 */
291 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
292 	/* error on OOB pointer computation */
293 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
294 	/* exit */
295 	BPF_MOV64_IMM(BPF_REG_0, 0),
296 	BPF_EXIT_INSN(),
297 	},
298 	.fixup_map_hash_8b = { 3 },
299 	.errstr = "value -4294967168 makes map_value pointer be out of bounds",
300 	.result = REJECT,
301 },
302 {
303 	"bounds check after wrapping 32-bit addition",
304 	.insns = {
305 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
306 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
307 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
308 	BPF_LD_MAP_FD(BPF_REG_1, 0),
309 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
310 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
311 	/* r1 = 0x7fff'ffff */
312 	BPF_MOV64_IMM(BPF_REG_1, 0x7fffffff),
313 	/* r1 = 0xffff'fffe */
314 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
315 	/* r1 = 0 */
316 	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 2),
317 	/* no-op */
318 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
319 	/* access at offset 0 */
320 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
321 	/* exit */
322 	BPF_MOV64_IMM(BPF_REG_0, 0),
323 	BPF_EXIT_INSN(),
324 	},
325 	.fixup_map_hash_8b = { 3 },
326 	.result = ACCEPT
327 },
328 {
329 	"bounds check after shift with oversized count operand",
330 	.insns = {
331 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
332 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
333 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
334 	BPF_LD_MAP_FD(BPF_REG_1, 0),
335 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
336 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
337 	BPF_MOV64_IMM(BPF_REG_2, 32),
338 	BPF_MOV64_IMM(BPF_REG_1, 1),
339 	/* r1 = (u32)1 << (u32)32 = ? */
340 	BPF_ALU32_REG(BPF_LSH, BPF_REG_1, BPF_REG_2),
341 	/* r1 = [0x0000, 0xffff] */
342 	BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xffff),
343 	/* computes unknown pointer, potentially OOB */
344 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
345 	/* potentially OOB access */
346 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
347 	/* exit */
348 	BPF_MOV64_IMM(BPF_REG_0, 0),
349 	BPF_EXIT_INSN(),
350 	},
351 	.fixup_map_hash_8b = { 3 },
352 	.errstr = "R0 max value is outside of the allowed memory range",
353 	.result = REJECT
354 },
355 {
356 	"bounds check after right shift of maybe-negative number",
357 	.insns = {
358 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
359 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
360 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
361 	BPF_LD_MAP_FD(BPF_REG_1, 0),
362 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
363 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
364 	/* r1 = [0x00, 0xff] */
365 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
366 	/* r1 = [-0x01, 0xfe] */
367 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
368 	/* r1 = 0 or 0xff'ffff'ffff'ffff */
369 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
370 	/* r1 = 0 or 0xffff'ffff'ffff */
371 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
372 	/* computes unknown pointer, potentially OOB */
373 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
374 	/* potentially OOB access */
375 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
376 	/* exit */
377 	BPF_MOV64_IMM(BPF_REG_0, 0),
378 	BPF_EXIT_INSN(),
379 	},
380 	.fixup_map_hash_8b = { 3 },
381 	.errstr = "R0 unbounded memory access",
382 	.result = REJECT
383 },
384 {
385 	"bounds check after 32-bit right shift with 64-bit input",
386 	.insns = {
387 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
388 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
389 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
390 	BPF_LD_MAP_FD(BPF_REG_1, 0),
391 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
392 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
393 	/* r1 = 2 */
394 	BPF_MOV64_IMM(BPF_REG_1, 2),
395 	/* r1 = 1<<32 */
396 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31),
397 	/* r1 = 0 (NOT 2!) */
398 	BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31),
399 	/* r1 = 0xffff'fffe (NOT 0!) */
400 	BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2),
401 	/* error on computing OOB pointer */
402 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
403 	/* exit */
404 	BPF_MOV64_IMM(BPF_REG_0, 0),
405 	BPF_EXIT_INSN(),
406 	},
407 	.fixup_map_hash_8b = { 3 },
408 	.errstr = "math between map_value pointer and 4294967294 is not allowed",
409 	.result = REJECT,
410 },
411 {
412 	"bounds check map access with off+size signed 32bit overflow. test1",
413 	.insns = {
414 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
415 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
416 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
417 	BPF_LD_MAP_FD(BPF_REG_1, 0),
418 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
419 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
420 	BPF_EXIT_INSN(),
421 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe),
422 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
423 	BPF_JMP_A(0),
424 	BPF_EXIT_INSN(),
425 	},
426 	.fixup_map_hash_8b = { 3 },
427 	.errstr = "map_value pointer and 2147483646",
428 	.result = REJECT
429 },
430 {
431 	"bounds check map access with off+size signed 32bit overflow. test2",
432 	.insns = {
433 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
434 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
435 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
436 	BPF_LD_MAP_FD(BPF_REG_1, 0),
437 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
438 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
439 	BPF_EXIT_INSN(),
440 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
441 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
442 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
443 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
444 	BPF_JMP_A(0),
445 	BPF_EXIT_INSN(),
446 	},
447 	.fixup_map_hash_8b = { 3 },
448 	.errstr = "pointer offset 1073741822",
449 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
450 	.result = REJECT
451 },
452 {
453 	"bounds check map access with off+size signed 32bit overflow. test3",
454 	.insns = {
455 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
456 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
457 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
458 	BPF_LD_MAP_FD(BPF_REG_1, 0),
459 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
460 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
461 	BPF_EXIT_INSN(),
462 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
463 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
464 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
465 	BPF_JMP_A(0),
466 	BPF_EXIT_INSN(),
467 	},
468 	.fixup_map_hash_8b = { 3 },
469 	.errstr = "pointer offset -1073741822",
470 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
471 	.result = REJECT
472 },
473 {
474 	"bounds check map access with off+size signed 32bit overflow. test4",
475 	.insns = {
476 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
477 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
478 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
479 	BPF_LD_MAP_FD(BPF_REG_1, 0),
480 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
481 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
482 	BPF_EXIT_INSN(),
483 	BPF_MOV64_IMM(BPF_REG_1, 1000000),
484 	BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000),
485 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
486 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
487 	BPF_JMP_A(0),
488 	BPF_EXIT_INSN(),
489 	},
490 	.fixup_map_hash_8b = { 3 },
491 	.errstr = "map_value pointer and 1000000000000",
492 	.result = REJECT
493 },
494 {
495 	"bounds check mixed 32bit and 64bit arithmetic. test1",
496 	.insns = {
497 	BPF_MOV64_IMM(BPF_REG_0, 0),
498 	BPF_MOV64_IMM(BPF_REG_1, -1),
499 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
500 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
501 	/* r1 = 0xffffFFFF00000001 */
502 	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 1, 3),
503 	/* check ALU64 op keeps 32bit bounds */
504 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
505 	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 2, 1),
506 	BPF_JMP_A(1),
507 	/* invalid ldx if bounds are lost above */
508 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
509 	BPF_EXIT_INSN(),
510 	},
511 	.result = ACCEPT
512 },
513 {
514 	"bounds check mixed 32bit and 64bit arithmetic. test2",
515 	.insns = {
516 	BPF_MOV64_IMM(BPF_REG_0, 0),
517 	BPF_MOV64_IMM(BPF_REG_1, -1),
518 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
519 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
520 	/* r1 = 0xffffFFFF00000001 */
521 	BPF_MOV64_IMM(BPF_REG_2, 3),
522 	/* r1 = 0x2 */
523 	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
524 	/* check ALU32 op zero extends 64bit bounds */
525 	BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1),
526 	BPF_JMP_A(1),
527 	/* invalid ldx if bounds are lost above */
528 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
529 	BPF_EXIT_INSN(),
530 	},
531 	.result = ACCEPT
532 },
533 {
534 	"assigning 32bit bounds to 64bit for wA = 0, wB = wA",
535 	.insns = {
536 	BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
537 		    offsetof(struct __sk_buff, data_end)),
538 	BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
539 		    offsetof(struct __sk_buff, data)),
540 	BPF_MOV32_IMM(BPF_REG_9, 0),
541 	BPF_MOV32_REG(BPF_REG_2, BPF_REG_9),
542 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_7),
543 	BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_2),
544 	BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
545 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8),
546 	BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_8, 1),
547 	BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_6, 0),
548 	BPF_MOV64_IMM(BPF_REG_0, 0),
549 	BPF_EXIT_INSN(),
550 	},
551 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
552 	.result = ACCEPT,
553 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
554 },
555 {
556 	"bounds check for reg = 0, reg xor 1",
557 	.insns = {
558 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
559 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
560 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
561 	BPF_LD_MAP_FD(BPF_REG_1, 0),
562 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
563 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
564 	BPF_EXIT_INSN(),
565 	BPF_MOV64_IMM(BPF_REG_1, 0),
566 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 1),
567 	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
568 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
569 	BPF_MOV64_IMM(BPF_REG_0, 0),
570 	BPF_EXIT_INSN(),
571 	},
572 	.fixup_map_hash_8b = { 3 },
573 	.result = ACCEPT,
574 },
575 {
576 	"bounds check for reg32 = 0, reg32 xor 1",
577 	.insns = {
578 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
579 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
580 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
581 	BPF_LD_MAP_FD(BPF_REG_1, 0),
582 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
583 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
584 	BPF_EXIT_INSN(),
585 	BPF_MOV32_IMM(BPF_REG_1, 0),
586 	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 1),
587 	BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
588 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
589 	BPF_MOV64_IMM(BPF_REG_0, 0),
590 	BPF_EXIT_INSN(),
591 	},
592 	.fixup_map_hash_8b = { 3 },
593 	.result = ACCEPT,
594 },
595 {
596 	"bounds check for reg = 2, reg xor 3",
597 	.insns = {
598 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
599 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
600 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
601 	BPF_LD_MAP_FD(BPF_REG_1, 0),
602 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
603 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
604 	BPF_EXIT_INSN(),
605 	BPF_MOV64_IMM(BPF_REG_1, 2),
606 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
607 	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0, 1),
608 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
609 	BPF_MOV64_IMM(BPF_REG_0, 0),
610 	BPF_EXIT_INSN(),
611 	},
612 	.fixup_map_hash_8b = { 3 },
613 	.result = ACCEPT,
614 },
615 {
616 	"bounds check for reg = any, reg xor 3",
617 	.insns = {
618 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
619 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
620 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
621 	BPF_LD_MAP_FD(BPF_REG_1, 0),
622 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
623 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
624 	BPF_EXIT_INSN(),
625 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
626 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
627 	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
628 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
629 	BPF_MOV64_IMM(BPF_REG_0, 0),
630 	BPF_EXIT_INSN(),
631 	},
632 	.fixup_map_hash_8b = { 3 },
633 	.result = REJECT,
634 	.errstr = "invalid access to map value",
635 	.errstr_unpriv = "invalid access to map value",
636 },
637 {
638 	"bounds check for reg32 = any, reg32 xor 3",
639 	.insns = {
640 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
641 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
642 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
643 	BPF_LD_MAP_FD(BPF_REG_1, 0),
644 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
645 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
646 	BPF_EXIT_INSN(),
647 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
648 	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
649 	BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
650 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
651 	BPF_MOV64_IMM(BPF_REG_0, 0),
652 	BPF_EXIT_INSN(),
653 	},
654 	.fixup_map_hash_8b = { 3 },
655 	.result = REJECT,
656 	.errstr = "invalid access to map value",
657 	.errstr_unpriv = "invalid access to map value",
658 },
659 {
660 	"bounds check for reg > 0, reg xor 3",
661 	.insns = {
662 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
663 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
664 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
665 	BPF_LD_MAP_FD(BPF_REG_1, 0),
666 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
667 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
668 	BPF_EXIT_INSN(),
669 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
670 	BPF_JMP_IMM(BPF_JLE, BPF_REG_1, 0, 3),
671 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
672 	BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 1),
673 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
674 	BPF_MOV64_IMM(BPF_REG_0, 0),
675 	BPF_EXIT_INSN(),
676 	},
677 	.fixup_map_hash_8b = { 3 },
678 	.result = ACCEPT,
679 },
680 {
681 	"bounds check for reg32 > 0, reg32 xor 3",
682 	.insns = {
683 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
684 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
685 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
686 	BPF_LD_MAP_FD(BPF_REG_1, 0),
687 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
688 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
689 	BPF_EXIT_INSN(),
690 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
691 	BPF_JMP32_IMM(BPF_JLE, BPF_REG_1, 0, 3),
692 	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
693 	BPF_JMP32_IMM(BPF_JGE, BPF_REG_1, 0, 1),
694 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
695 	BPF_MOV64_IMM(BPF_REG_0, 0),
696 	BPF_EXIT_INSN(),
697 	},
698 	.fixup_map_hash_8b = { 3 },
699 	.result = ACCEPT,
700 },
701 {
702 	"bounds checks after 32-bit truncation. test 1",
703 	.insns = {
704 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
705 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
706 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
707 	BPF_LD_MAP_FD(BPF_REG_1, 0),
708 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
709 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
710 	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
711 	/* This used to reduce the max bound to 0x7fffffff */
712 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
713 	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0x7fffffff, 1),
714 	BPF_MOV64_IMM(BPF_REG_0, 0),
715 	BPF_EXIT_INSN(),
716 	},
717 	.fixup_map_hash_8b = { 3 },
718 	.errstr_unpriv = "R0 leaks addr",
719 	.result_unpriv = REJECT,
720 	.result = ACCEPT,
721 },
722 {
723 	"bounds checks after 32-bit truncation. test 2",
724 	.insns = {
725 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
726 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
727 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
728 	BPF_LD_MAP_FD(BPF_REG_1, 0),
729 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
730 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
731 	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
732 	BPF_JMP_IMM(BPF_JSLT, BPF_REG_1, 1, 1),
733 	BPF_JMP32_IMM(BPF_JSLT, BPF_REG_1, 0, 1),
734 	BPF_MOV64_IMM(BPF_REG_0, 0),
735 	BPF_EXIT_INSN(),
736 	},
737 	.fixup_map_hash_8b = { 3 },
738 	.errstr_unpriv = "R0 leaks addr",
739 	.result_unpriv = REJECT,
740 	.result = ACCEPT,
741 },
742