Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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_unpriv = "R1 has unknown scalar with mixed signed bounds, pointer arithmetic with it prohibited for !root",
265	.result_unpriv = REJECT,
266	.errstr = "value -4294967168 makes map_value pointer be out of bounds",
267	.result = REJECT,
268},
269{
270	"bounds check after truncation of boundary-crossing range (2)",
271	.insns = {
272	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
273	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
274	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
275	BPF_LD_MAP_FD(BPF_REG_1, 0),
276	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
277	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
278	/* r1 = [0x00, 0xff] */
279	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
280	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
281	/* r1 = [0xffff'ff80, 0x1'0000'007f] */
282	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
283	/* r1 = [0xffff'ff80, 0xffff'ffff] or
284	 *      [0x0000'0000, 0x0000'007f]
285	 * difference to previous test: truncation via MOV32
286	 * instead of ALU32.
287	 */
288	BPF_MOV32_REG(BPF_REG_1, BPF_REG_1),
289	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
290	/* r1 = [0x00, 0xff] or
291	 *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
292	 */
293	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
294	/* error on OOB pointer computation */
295	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
296	/* exit */
297	BPF_MOV64_IMM(BPF_REG_0, 0),
298	BPF_EXIT_INSN(),
299	},
300	.fixup_map_hash_8b = { 3 },
301	/* not actually fully unbounded, but the bound is very high */
302	.errstr_unpriv = "R1 has unknown scalar with mixed signed bounds, pointer arithmetic with it prohibited for !root",
303	.result_unpriv = REJECT,
304	.errstr = "value -4294967168 makes map_value pointer be out of bounds",
305	.result = REJECT,
306},
307{
308	"bounds check after wrapping 32-bit addition",
309	.insns = {
310	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
311	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
312	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
313	BPF_LD_MAP_FD(BPF_REG_1, 0),
314	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
315	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
316	/* r1 = 0x7fff'ffff */
317	BPF_MOV64_IMM(BPF_REG_1, 0x7fffffff),
318	/* r1 = 0xffff'fffe */
319	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
320	/* r1 = 0 */
321	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 2),
322	/* no-op */
323	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
324	/* access at offset 0 */
325	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
326	/* exit */
327	BPF_MOV64_IMM(BPF_REG_0, 0),
328	BPF_EXIT_INSN(),
329	},
330	.fixup_map_hash_8b = { 3 },
331	.result = ACCEPT
332},
333{
334	"bounds check after shift with oversized count operand",
335	.insns = {
336	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
337	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
338	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
339	BPF_LD_MAP_FD(BPF_REG_1, 0),
340	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
341	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
342	BPF_MOV64_IMM(BPF_REG_2, 32),
343	BPF_MOV64_IMM(BPF_REG_1, 1),
344	/* r1 = (u32)1 << (u32)32 = ? */
345	BPF_ALU32_REG(BPF_LSH, BPF_REG_1, BPF_REG_2),
346	/* r1 = [0x0000, 0xffff] */
347	BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xffff),
348	/* computes unknown pointer, potentially OOB */
349	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
350	/* potentially OOB access */
351	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
352	/* exit */
353	BPF_MOV64_IMM(BPF_REG_0, 0),
354	BPF_EXIT_INSN(),
355	},
356	.fixup_map_hash_8b = { 3 },
357	.errstr = "R0 max value is outside of the allowed memory range",
358	.result = REJECT
359},
360{
361	"bounds check after right shift of maybe-negative number",
362	.insns = {
363	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
364	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
365	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
366	BPF_LD_MAP_FD(BPF_REG_1, 0),
367	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
368	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
369	/* r1 = [0x00, 0xff] */
370	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
371	/* r1 = [-0x01, 0xfe] */
372	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
373	/* r1 = 0 or 0xff'ffff'ffff'ffff */
374	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
375	/* r1 = 0 or 0xffff'ffff'ffff */
376	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
377	/* computes unknown pointer, potentially OOB */
378	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
379	/* potentially OOB access */
380	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
381	/* exit */
382	BPF_MOV64_IMM(BPF_REG_0, 0),
383	BPF_EXIT_INSN(),
384	},
385	.fixup_map_hash_8b = { 3 },
386	.errstr = "R0 unbounded memory access",
387	.result = REJECT
388},
389{
390	"bounds check after 32-bit right shift with 64-bit input",
391	.insns = {
392	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
393	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
394	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
395	BPF_LD_MAP_FD(BPF_REG_1, 0),
396	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
397	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
398	/* r1 = 2 */
399	BPF_MOV64_IMM(BPF_REG_1, 2),
400	/* r1 = 1<<32 */
401	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31),
402	/* r1 = 0 (NOT 2!) */
403	BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31),
404	/* r1 = 0xffff'fffe (NOT 0!) */
405	BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2),
406	/* error on computing OOB pointer */
407	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
408	/* exit */
409	BPF_MOV64_IMM(BPF_REG_0, 0),
410	BPF_EXIT_INSN(),
411	},
412	.fixup_map_hash_8b = { 3 },
413	.errstr = "math between map_value pointer and 4294967294 is not allowed",
414	.result = REJECT,
415},
416{
417	"bounds check map access with off+size signed 32bit overflow. test1",
418	.insns = {
419	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
420	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
421	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
422	BPF_LD_MAP_FD(BPF_REG_1, 0),
423	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
424	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
425	BPF_EXIT_INSN(),
426	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe),
427	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
428	BPF_JMP_A(0),
429	BPF_EXIT_INSN(),
430	},
431	.fixup_map_hash_8b = { 3 },
432	.errstr = "map_value pointer and 2147483646",
433	.result = REJECT
434},
435{
436	"bounds check map access with off+size signed 32bit overflow. test2",
437	.insns = {
438	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
439	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
440	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
441	BPF_LD_MAP_FD(BPF_REG_1, 0),
442	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
443	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
444	BPF_EXIT_INSN(),
445	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
446	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
447	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
448	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
449	BPF_JMP_A(0),
450	BPF_EXIT_INSN(),
451	},
452	.fixup_map_hash_8b = { 3 },
453	.errstr = "pointer offset 1073741822",
454	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
455	.result = REJECT
456},
457{
458	"bounds check map access with off+size signed 32bit overflow. test3",
459	.insns = {
460	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
461	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
462	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
463	BPF_LD_MAP_FD(BPF_REG_1, 0),
464	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
465	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
466	BPF_EXIT_INSN(),
467	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
468	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
469	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
470	BPF_JMP_A(0),
471	BPF_EXIT_INSN(),
472	},
473	.fixup_map_hash_8b = { 3 },
474	.errstr = "pointer offset -1073741822",
475	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
476	.result = REJECT
477},
478{
479	"bounds check map access with off+size signed 32bit overflow. test4",
480	.insns = {
481	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
482	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
483	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
484	BPF_LD_MAP_FD(BPF_REG_1, 0),
485	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
486	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
487	BPF_EXIT_INSN(),
488	BPF_MOV64_IMM(BPF_REG_1, 1000000),
489	BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000),
490	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
491	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
492	BPF_JMP_A(0),
493	BPF_EXIT_INSN(),
494	},
495	.fixup_map_hash_8b = { 3 },
496	.errstr = "map_value pointer and 1000000000000",
497	.result = REJECT
498},
499{
500	"bounds check mixed 32bit and 64bit arithmetic. test1",
501	.insns = {
502	BPF_MOV64_IMM(BPF_REG_0, 0),
503	BPF_MOV64_IMM(BPF_REG_1, -1),
504	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
505	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
506	/* r1 = 0xffffFFFF00000001 */
507	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 1, 3),
508	/* check ALU64 op keeps 32bit bounds */
509	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
510	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 2, 1),
511	BPF_JMP_A(1),
512	/* invalid ldx if bounds are lost above */
513	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
514	BPF_EXIT_INSN(),
515	},
516	.result = ACCEPT
517},
518{
519	"bounds check mixed 32bit and 64bit arithmetic. test2",
520	.insns = {
521	BPF_MOV64_IMM(BPF_REG_0, 0),
522	BPF_MOV64_IMM(BPF_REG_1, -1),
523	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
524	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
525	/* r1 = 0xffffFFFF00000001 */
526	BPF_MOV64_IMM(BPF_REG_2, 3),
527	/* r1 = 0x2 */
528	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
529	/* check ALU32 op zero extends 64bit bounds */
530	BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1),
531	BPF_JMP_A(1),
532	/* invalid ldx if bounds are lost above */
533	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
534	BPF_EXIT_INSN(),
535	},
536	.result = ACCEPT
537},
538{
539	"assigning 32bit bounds to 64bit for wA = 0, wB = wA",
540	.insns = {
541	BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
542		    offsetof(struct __sk_buff, data_end)),
543	BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
544		    offsetof(struct __sk_buff, data)),
545	BPF_MOV32_IMM(BPF_REG_9, 0),
546	BPF_MOV32_REG(BPF_REG_2, BPF_REG_9),
547	BPF_MOV64_REG(BPF_REG_6, BPF_REG_7),
548	BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_2),
549	BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
550	BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8),
551	BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_8, 1),
552	BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_6, 0),
553	BPF_MOV64_IMM(BPF_REG_0, 0),
554	BPF_EXIT_INSN(),
555	},
556	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
557	.result = ACCEPT,
558	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
559},