• 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 	/* error on computing OOB pointer */
415 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
416 	/* exit */
417 	BPF_MOV64_IMM(BPF_REG_0, 0),
418 	BPF_EXIT_INSN(),
419 	},
420 	.fixup_map_hash_8b = { 3 },
421 	.errstr = "math between map_value pointer and 4294967294 is not allowed",
422 	.result = REJECT,
423 },
424 {
425 	"bounds check map access with off+size signed 32bit overflow. test1",
426 	.insns = {
427 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
428 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
429 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
430 	BPF_LD_MAP_FD(BPF_REG_1, 0),
431 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
432 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
433 	BPF_EXIT_INSN(),
434 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe),
435 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
436 	BPF_JMP_A(0),
437 	BPF_EXIT_INSN(),
438 	},
439 	.fixup_map_hash_8b = { 3 },
440 	.errstr = "map_value pointer and 2147483646",
441 	.result = REJECT
442 },
443 {
444 	"bounds check map access with off+size signed 32bit overflow. test2",
445 	.insns = {
446 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
447 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
448 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
449 	BPF_LD_MAP_FD(BPF_REG_1, 0),
450 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
451 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
452 	BPF_EXIT_INSN(),
453 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
454 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
455 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
456 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
457 	BPF_JMP_A(0),
458 	BPF_EXIT_INSN(),
459 	},
460 	.fixup_map_hash_8b = { 3 },
461 	.errstr = "pointer offset 1073741822",
462 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
463 	.result = REJECT
464 },
465 {
466 	"bounds check map access with off+size signed 32bit overflow. test3",
467 	.insns = {
468 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
469 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
470 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
471 	BPF_LD_MAP_FD(BPF_REG_1, 0),
472 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
473 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
474 	BPF_EXIT_INSN(),
475 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
476 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
477 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
478 	BPF_JMP_A(0),
479 	BPF_EXIT_INSN(),
480 	},
481 	.fixup_map_hash_8b = { 3 },
482 	.errstr = "pointer offset -1073741822",
483 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
484 	.result = REJECT
485 },
486 {
487 	"bounds check map access with off+size signed 32bit overflow. test4",
488 	.insns = {
489 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
490 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
491 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
492 	BPF_LD_MAP_FD(BPF_REG_1, 0),
493 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
494 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
495 	BPF_EXIT_INSN(),
496 	BPF_MOV64_IMM(BPF_REG_1, 1000000),
497 	BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000),
498 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
499 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
500 	BPF_JMP_A(0),
501 	BPF_EXIT_INSN(),
502 	},
503 	.fixup_map_hash_8b = { 3 },
504 	.errstr = "map_value pointer and 1000000000000",
505 	.result = REJECT
506 },
507 {
508 	"bounds check mixed 32bit and 64bit arithmatic. test1",
509 	.insns = {
510 	BPF_MOV64_IMM(BPF_REG_0, 0),
511 	BPF_MOV64_IMM(BPF_REG_1, -1),
512 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
513 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
514 	/* r1 = 0xffffFFFF00000001 */
515 	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 1, 3),
516 	/* check ALU64 op keeps 32bit bounds */
517 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
518 	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 2, 1),
519 	BPF_JMP_A(1),
520 	/* invalid ldx if bounds are lost above */
521 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
522 	BPF_EXIT_INSN(),
523 	},
524 	.errstr_unpriv = "R0 invalid mem access 'inv'",
525 	.result_unpriv = REJECT,
526 	.result = ACCEPT
527 },
528 {
529 	"bounds check mixed 32bit and 64bit arithmatic. test2",
530 	.insns = {
531 	BPF_MOV64_IMM(BPF_REG_0, 0),
532 	BPF_MOV64_IMM(BPF_REG_1, -1),
533 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
534 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
535 	/* r1 = 0xffffFFFF00000001 */
536 	BPF_MOV64_IMM(BPF_REG_2, 3),
537 	/* r1 = 0x2 */
538 	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
539 	/* check ALU32 op zero extends 64bit bounds */
540 	BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1),
541 	BPF_JMP_A(1),
542 	/* invalid ldx if bounds are lost above */
543 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
544 	BPF_EXIT_INSN(),
545 	},
546 	.errstr_unpriv = "R0 invalid mem access 'inv'",
547 	.result_unpriv = REJECT,
548 	.result = ACCEPT
549 },
550 {
551 	"assigning 32bit bounds to 64bit for wA = 0, wB = wA",
552 	.insns = {
553 	BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
554 		    offsetof(struct __sk_buff, data_end)),
555 	BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
556 		    offsetof(struct __sk_buff, data)),
557 	BPF_MOV32_IMM(BPF_REG_9, 0),
558 	BPF_MOV32_REG(BPF_REG_2, BPF_REG_9),
559 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_7),
560 	BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_2),
561 	BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
562 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8),
563 	BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_8, 1),
564 	BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_6, 0),
565 	BPF_MOV64_IMM(BPF_REG_0, 0),
566 	BPF_EXIT_INSN(),
567 	},
568 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
569 	.result = ACCEPT,
570 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
571 },
572