Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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},