Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / tools / testing / selftests / bpf / verifier / bounds.c
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 },