• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	/* no-op or OOB pointer computation */
261 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
262 	/* potentially OOB access */
263 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
264 	/* exit */
265 	BPF_MOV64_IMM(BPF_REG_0, 0),
266 	BPF_EXIT_INSN(),
267 	},
268 	.fixup_map_hash_8b = { 3 },
269 	/* not actually fully unbounded, but the bound is very high */
270 	.errstr = "R0 unbounded memory access",
271 	.result = REJECT
272 },
273 {
274 	"bounds check after truncation of boundary-crossing range (2)",
275 	.insns = {
276 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
277 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
278 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
279 	BPF_LD_MAP_FD(BPF_REG_1, 0),
280 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
281 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
282 	/* r1 = [0x00, 0xff] */
283 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
284 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
285 	/* r1 = [0xffff'ff80, 0x1'0000'007f] */
286 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
287 	/* r1 = [0xffff'ff80, 0xffff'ffff] or
288 	 *      [0x0000'0000, 0x0000'007f]
289 	 * difference to previous test: truncation via MOV32
290 	 * instead of ALU32.
291 	 */
292 	BPF_MOV32_REG(BPF_REG_1, BPF_REG_1),
293 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
294 	/* r1 = [0x00, 0xff] or
295 	 *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
296 	 */
297 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
298 	/* r1 = 0 or
299 	 *      [0x00ff'ffff'ff00'0000, 0x00ff'ffff'ffff'ffff]
300 	 */
301 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
302 	/* no-op or OOB pointer computation */
303 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
304 	/* potentially OOB access */
305 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
306 	/* exit */
307 	BPF_MOV64_IMM(BPF_REG_0, 0),
308 	BPF_EXIT_INSN(),
309 	},
310 	.fixup_map_hash_8b = { 3 },
311 	/* not actually fully unbounded, but the bound is very high */
312 	.errstr = "R0 unbounded memory access",
313 	.result = REJECT
314 },
315 {
316 	"bounds check after wrapping 32-bit addition",
317 	.insns = {
318 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
319 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
320 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
321 	BPF_LD_MAP_FD(BPF_REG_1, 0),
322 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
323 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
324 	/* r1 = 0x7fff'ffff */
325 	BPF_MOV64_IMM(BPF_REG_1, 0x7fffffff),
326 	/* r1 = 0xffff'fffe */
327 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
328 	/* r1 = 0 */
329 	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 2),
330 	/* no-op */
331 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
332 	/* access at offset 0 */
333 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
334 	/* exit */
335 	BPF_MOV64_IMM(BPF_REG_0, 0),
336 	BPF_EXIT_INSN(),
337 	},
338 	.fixup_map_hash_8b = { 3 },
339 	.result = ACCEPT
340 },
341 {
342 	"bounds check after shift with oversized count operand",
343 	.insns = {
344 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
345 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
346 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
347 	BPF_LD_MAP_FD(BPF_REG_1, 0),
348 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
349 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
350 	BPF_MOV64_IMM(BPF_REG_2, 32),
351 	BPF_MOV64_IMM(BPF_REG_1, 1),
352 	/* r1 = (u32)1 << (u32)32 = ? */
353 	BPF_ALU32_REG(BPF_LSH, BPF_REG_1, BPF_REG_2),
354 	/* r1 = [0x0000, 0xffff] */
355 	BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xffff),
356 	/* computes unknown pointer, potentially OOB */
357 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
358 	/* potentially OOB access */
359 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
360 	/* exit */
361 	BPF_MOV64_IMM(BPF_REG_0, 0),
362 	BPF_EXIT_INSN(),
363 	},
364 	.fixup_map_hash_8b = { 3 },
365 	.errstr = "R0 max value is outside of the array range",
366 	.result = REJECT
367 },
368 {
369 	"bounds check after right shift of maybe-negative number",
370 	.insns = {
371 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
372 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
373 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
374 	BPF_LD_MAP_FD(BPF_REG_1, 0),
375 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
376 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
377 	/* r1 = [0x00, 0xff] */
378 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
379 	/* r1 = [-0x01, 0xfe] */
380 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
381 	/* r1 = 0 or 0xff'ffff'ffff'ffff */
382 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
383 	/* r1 = 0 or 0xffff'ffff'ffff */
384 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
385 	/* computes unknown pointer, potentially OOB */
386 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
387 	/* potentially OOB access */
388 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
389 	/* exit */
390 	BPF_MOV64_IMM(BPF_REG_0, 0),
391 	BPF_EXIT_INSN(),
392 	},
393 	.fixup_map_hash_8b = { 3 },
394 	.errstr = "R0 unbounded memory access",
395 	.result = REJECT
396 },
397 {
398 	"bounds check after 32-bit right shift with 64-bit input",
399 	.insns = {
400 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
401 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
402 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
403 	BPF_LD_MAP_FD(BPF_REG_1, 0),
404 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
405 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
406 	/* r1 = 2 */
407 	BPF_MOV64_IMM(BPF_REG_1, 2),
408 	/* r1 = 1<<32 */
409 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31),
410 	/* r1 = 0 (NOT 2!) */
411 	BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31),
412 	/* r1 = 0xffff'fffe (NOT 0!) */
413 	BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2),
414 	/* computes OOB pointer */
415 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
416 	/* OOB access */
417 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
418 	/* exit */
419 	BPF_MOV64_IMM(BPF_REG_0, 0),
420 	BPF_EXIT_INSN(),
421 	},
422 	.fixup_map_hash_8b = { 3 },
423 	.errstr = "R0 invalid mem access",
424 	.result = REJECT,
425 },
426 {
427 	"bounds check map access with off+size signed 32bit overflow. test1",
428 	.insns = {
429 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
430 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
431 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
432 	BPF_LD_MAP_FD(BPF_REG_1, 0),
433 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
434 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
435 	BPF_EXIT_INSN(),
436 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe),
437 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
438 	BPF_JMP_A(0),
439 	BPF_EXIT_INSN(),
440 	},
441 	.fixup_map_hash_8b = { 3 },
442 	.errstr = "map_value pointer and 2147483646",
443 	.result = REJECT
444 },
445 {
446 	"bounds check map access with off+size signed 32bit overflow. test2",
447 	.insns = {
448 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
449 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
450 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
451 	BPF_LD_MAP_FD(BPF_REG_1, 0),
452 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
453 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
454 	BPF_EXIT_INSN(),
455 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
456 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
457 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
458 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
459 	BPF_JMP_A(0),
460 	BPF_EXIT_INSN(),
461 	},
462 	.fixup_map_hash_8b = { 3 },
463 	.errstr = "pointer offset 1073741822",
464 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
465 	.result = REJECT
466 },
467 {
468 	"bounds check map access with off+size signed 32bit overflow. test3",
469 	.insns = {
470 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
471 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
472 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
473 	BPF_LD_MAP_FD(BPF_REG_1, 0),
474 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
475 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
476 	BPF_EXIT_INSN(),
477 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
478 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
479 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
480 	BPF_JMP_A(0),
481 	BPF_EXIT_INSN(),
482 	},
483 	.fixup_map_hash_8b = { 3 },
484 	.errstr = "pointer offset -1073741822",
485 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
486 	.result = REJECT
487 },
488 {
489 	"bounds check map access with off+size signed 32bit overflow. test4",
490 	.insns = {
491 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
492 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
493 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
494 	BPF_LD_MAP_FD(BPF_REG_1, 0),
495 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
496 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
497 	BPF_EXIT_INSN(),
498 	BPF_MOV64_IMM(BPF_REG_1, 1000000),
499 	BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000),
500 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
501 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
502 	BPF_JMP_A(0),
503 	BPF_EXIT_INSN(),
504 	},
505 	.fixup_map_hash_8b = { 3 },
506 	.errstr = "map_value pointer and 1000000000000",
507 	.result = REJECT
508 },
509