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	.errstr_unpriv = "R0 invalid mem access 'inv'",
512	.result_unpriv = REJECT,
513	.result = ACCEPT
514},
515{
516	"bounds check mixed 32bit and 64bit arithmetic. test2",
517	.insns = {
518	BPF_MOV64_IMM(BPF_REG_0, 0),
519	BPF_MOV64_IMM(BPF_REG_1, -1),
520	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
521	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
522	/* r1 = 0xffffFFFF00000001 */
523	BPF_MOV64_IMM(BPF_REG_2, 3),
524	/* r1 = 0x2 */
525	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
526	/* check ALU32 op zero extends 64bit bounds */
527	BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1),
528	BPF_JMP_A(1),
529	/* invalid ldx if bounds are lost above */
530	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
531	BPF_EXIT_INSN(),
532	},
533	.errstr_unpriv = "R0 invalid mem access 'inv'",
534	.result_unpriv = REJECT,
535	.result = ACCEPT
536},
537{
538	"assigning 32bit bounds to 64bit for wA = 0, wB = wA",
539	.insns = {
540	BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
541		    offsetof(struct __sk_buff, data_end)),
542	BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
543		    offsetof(struct __sk_buff, data)),
544	BPF_MOV32_IMM(BPF_REG_9, 0),
545	BPF_MOV32_REG(BPF_REG_2, BPF_REG_9),
546	BPF_MOV64_REG(BPF_REG_6, BPF_REG_7),
547	BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_2),
548	BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
549	BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8),
550	BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_8, 1),
551	BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_6, 0),
552	BPF_MOV64_IMM(BPF_REG_0, 0),
553	BPF_EXIT_INSN(),
554	},
555	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
556	.result = ACCEPT,
557	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
558},
559{
560	"bounds check for reg = 0, reg xor 1",
561	.insns = {
562	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
563	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
564	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
565	BPF_LD_MAP_FD(BPF_REG_1, 0),
566	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
567	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
568	BPF_EXIT_INSN(),
569	BPF_MOV64_IMM(BPF_REG_1, 0),
570	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 1),
571	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
572	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
573	BPF_MOV64_IMM(BPF_REG_0, 0),
574	BPF_EXIT_INSN(),
575	},
576	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
577	.result_unpriv = REJECT,
578	.fixup_map_hash_8b = { 3 },
579	.result = ACCEPT,
580},
581{
582	"bounds check for reg32 = 0, reg32 xor 1",
583	.insns = {
584	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
585	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
586	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
587	BPF_LD_MAP_FD(BPF_REG_1, 0),
588	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
589	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
590	BPF_EXIT_INSN(),
591	BPF_MOV32_IMM(BPF_REG_1, 0),
592	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 1),
593	BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
594	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
595	BPF_MOV64_IMM(BPF_REG_0, 0),
596	BPF_EXIT_INSN(),
597	},
598	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
599	.result_unpriv = REJECT,
600	.fixup_map_hash_8b = { 3 },
601	.result = ACCEPT,
602},
603{
604	"bounds check for reg = 2, reg xor 3",
605	.insns = {
606	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
607	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
608	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
609	BPF_LD_MAP_FD(BPF_REG_1, 0),
610	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
611	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
612	BPF_EXIT_INSN(),
613	BPF_MOV64_IMM(BPF_REG_1, 2),
614	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
615	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0, 1),
616	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
617	BPF_MOV64_IMM(BPF_REG_0, 0),
618	BPF_EXIT_INSN(),
619	},
620	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
621	.result_unpriv = REJECT,
622	.fixup_map_hash_8b = { 3 },
623	.result = ACCEPT,
624},
625{
626	"bounds check for reg = any, reg xor 3",
627	.insns = {
628	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
629	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
630	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
631	BPF_LD_MAP_FD(BPF_REG_1, 0),
632	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
633	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
634	BPF_EXIT_INSN(),
635	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
636	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
637	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
638	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
639	BPF_MOV64_IMM(BPF_REG_0, 0),
640	BPF_EXIT_INSN(),
641	},
642	.fixup_map_hash_8b = { 3 },
643	.result = REJECT,
644	.errstr = "invalid access to map value",
645	.errstr_unpriv = "invalid access to map value",
646},
647{
648	"bounds check for reg32 = any, reg32 xor 3",
649	.insns = {
650	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
651	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
652	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
653	BPF_LD_MAP_FD(BPF_REG_1, 0),
654	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
655	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
656	BPF_EXIT_INSN(),
657	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
658	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
659	BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
660	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
661	BPF_MOV64_IMM(BPF_REG_0, 0),
662	BPF_EXIT_INSN(),
663	},
664	.fixup_map_hash_8b = { 3 },
665	.result = REJECT,
666	.errstr = "invalid access to map value",
667	.errstr_unpriv = "invalid access to map value",
668},
669{
670	"bounds check for reg > 0, reg xor 3",
671	.insns = {
672	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
673	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
674	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
675	BPF_LD_MAP_FD(BPF_REG_1, 0),
676	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
677	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
678	BPF_EXIT_INSN(),
679	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
680	BPF_JMP_IMM(BPF_JLE, BPF_REG_1, 0, 3),
681	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
682	BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 1),
683	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
684	BPF_MOV64_IMM(BPF_REG_0, 0),
685	BPF_EXIT_INSN(),
686	},
687	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
688	.result_unpriv = REJECT,
689	.fixup_map_hash_8b = { 3 },
690	.result = ACCEPT,
691},
692{
693	"bounds check for reg32 > 0, reg32 xor 3",
694	.insns = {
695	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
696	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
697	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
698	BPF_LD_MAP_FD(BPF_REG_1, 0),
699	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
700	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
701	BPF_EXIT_INSN(),
702	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
703	BPF_JMP32_IMM(BPF_JLE, BPF_REG_1, 0, 3),
704	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
705	BPF_JMP32_IMM(BPF_JGE, BPF_REG_1, 0, 1),
706	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
707	BPF_MOV64_IMM(BPF_REG_0, 0),
708	BPF_EXIT_INSN(),
709	},
710	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
711	.result_unpriv = REJECT,
712	.fixup_map_hash_8b = { 3 },
713	.result = ACCEPT,
714},
715{
716	"bounds checks after 32-bit truncation. test 1",
717	.insns = {
718	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
719	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
720	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
721	BPF_LD_MAP_FD(BPF_REG_1, 0),
722	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
723	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
724	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
725	/* This used to reduce the max bound to 0x7fffffff */
726	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
727	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0x7fffffff, 1),
728	BPF_MOV64_IMM(BPF_REG_0, 0),
729	BPF_EXIT_INSN(),
730	},
731	.fixup_map_hash_8b = { 3 },
732	.errstr_unpriv = "R0 leaks addr",
733	.result_unpriv = REJECT,
734	.result = ACCEPT,
735},
736{
737	"bounds checks after 32-bit truncation. test 2",
738	.insns = {
739	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
740	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
741	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
742	BPF_LD_MAP_FD(BPF_REG_1, 0),
743	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
744	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
745	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
746	BPF_JMP_IMM(BPF_JSLT, BPF_REG_1, 1, 1),
747	BPF_JMP32_IMM(BPF_JSLT, BPF_REG_1, 0, 1),
748	BPF_MOV64_IMM(BPF_REG_0, 0),
749	BPF_EXIT_INSN(),
750	},
751	.fixup_map_hash_8b = { 3 },
752	.errstr_unpriv = "R0 leaks addr",
753	.result_unpriv = REJECT,
754	.result = ACCEPT,
755},
756