1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Converted from tools/testing/selftests/bpf/verifier/unpriv.c */ |
3 | |
4 | #include <linux/bpf.h> |
5 | #include <bpf/bpf_helpers.h> |
6 | #include "../../../include/linux/filter.h" |
7 | #include "bpf_misc.h" |
8 | |
9 | #define BPF_SK_LOOKUP(func) \ |
10 | /* struct bpf_sock_tuple tuple = {} */ \ |
11 | "r2 = 0;" \ |
12 | "*(u32*)(r10 - 8) = r2;" \ |
13 | "*(u64*)(r10 - 16) = r2;" \ |
14 | "*(u64*)(r10 - 24) = r2;" \ |
15 | "*(u64*)(r10 - 32) = r2;" \ |
16 | "*(u64*)(r10 - 40) = r2;" \ |
17 | "*(u64*)(r10 - 48) = r2;" \ |
18 | /* sk = func(ctx, &tuple, sizeof tuple, 0, 0) */ \ |
19 | "r2 = r10;" \ |
20 | "r2 += -48;" \ |
21 | "r3 = %[sizeof_bpf_sock_tuple];"\ |
22 | "r4 = 0;" \ |
23 | "r5 = 0;" \ |
24 | "call %[" #func "];" |
25 | |
26 | struct { |
27 | __uint(type, BPF_MAP_TYPE_HASH); |
28 | __uint(max_entries, 1); |
29 | __type(key, long long); |
30 | __type(value, long long); |
31 | } map_hash_8b SEC(".maps" ); |
32 | |
33 | void dummy_prog_42_socket(void); |
34 | void dummy_prog_24_socket(void); |
35 | void dummy_prog_loop1_socket(void); |
36 | |
37 | struct { |
38 | __uint(type, BPF_MAP_TYPE_PROG_ARRAY); |
39 | __uint(max_entries, 4); |
40 | __uint(key_size, sizeof(int)); |
41 | __array(values, void (void)); |
42 | } map_prog1_socket SEC(".maps" ) = { |
43 | .values = { |
44 | [0] = (void *)&dummy_prog_42_socket, |
45 | [1] = (void *)&dummy_prog_loop1_socket, |
46 | [2] = (void *)&dummy_prog_24_socket, |
47 | }, |
48 | }; |
49 | |
50 | SEC("socket" ) |
51 | __auxiliary __auxiliary_unpriv |
52 | __naked void dummy_prog_42_socket(void) |
53 | { |
54 | asm volatile ("r0 = 42; exit;" ); |
55 | } |
56 | |
57 | SEC("socket" ) |
58 | __auxiliary __auxiliary_unpriv |
59 | __naked void dummy_prog_24_socket(void) |
60 | { |
61 | asm volatile ("r0 = 24; exit;" ); |
62 | } |
63 | |
64 | SEC("socket" ) |
65 | __auxiliary __auxiliary_unpriv |
66 | __naked void dummy_prog_loop1_socket(void) |
67 | { |
68 | asm volatile (" \ |
69 | r3 = 1; \ |
70 | r2 = %[map_prog1_socket] ll; \ |
71 | call %[bpf_tail_call]; \ |
72 | r0 = 41; \ |
73 | exit; \ |
74 | " : |
75 | : __imm(bpf_tail_call), |
76 | __imm_addr(map_prog1_socket) |
77 | : __clobber_all); |
78 | } |
79 | |
80 | SEC("socket" ) |
81 | __description("unpriv: return pointer" ) |
82 | __success __failure_unpriv __msg_unpriv("R0 leaks addr" ) |
83 | __retval(POINTER_VALUE) |
84 | __naked void unpriv_return_pointer(void) |
85 | { |
86 | asm volatile (" \ |
87 | r0 = r10; \ |
88 | exit; \ |
89 | " ::: __clobber_all); |
90 | } |
91 | |
92 | SEC("socket" ) |
93 | __description("unpriv: add const to pointer" ) |
94 | __success __success_unpriv __retval(0) |
95 | __naked void unpriv_add_const_to_pointer(void) |
96 | { |
97 | asm volatile (" \ |
98 | r1 += 8; \ |
99 | r0 = 0; \ |
100 | exit; \ |
101 | " ::: __clobber_all); |
102 | } |
103 | |
104 | SEC("socket" ) |
105 | __description("unpriv: add pointer to pointer" ) |
106 | __failure __msg("R1 pointer += pointer" ) |
107 | __failure_unpriv |
108 | __naked void unpriv_add_pointer_to_pointer(void) |
109 | { |
110 | asm volatile (" \ |
111 | r1 += r10; \ |
112 | r0 = 0; \ |
113 | exit; \ |
114 | " ::: __clobber_all); |
115 | } |
116 | |
117 | SEC("socket" ) |
118 | __description("unpriv: neg pointer" ) |
119 | __success __failure_unpriv __msg_unpriv("R1 pointer arithmetic" ) |
120 | __retval(0) |
121 | __naked void unpriv_neg_pointer(void) |
122 | { |
123 | asm volatile (" \ |
124 | r1 = -r1; \ |
125 | r0 = 0; \ |
126 | exit; \ |
127 | " ::: __clobber_all); |
128 | } |
129 | |
130 | SEC("socket" ) |
131 | __description("unpriv: cmp pointer with const" ) |
132 | __success __failure_unpriv __msg_unpriv("R1 pointer comparison" ) |
133 | __retval(0) |
134 | __naked void unpriv_cmp_pointer_with_const(void) |
135 | { |
136 | asm volatile (" \ |
137 | if r1 == 0 goto l0_%=; \ |
138 | l0_%=: r0 = 0; \ |
139 | exit; \ |
140 | " ::: __clobber_all); |
141 | } |
142 | |
143 | SEC("socket" ) |
144 | __description("unpriv: cmp pointer with pointer" ) |
145 | __success __failure_unpriv __msg_unpriv("R10 pointer comparison" ) |
146 | __retval(0) |
147 | __naked void unpriv_cmp_pointer_with_pointer(void) |
148 | { |
149 | asm volatile (" \ |
150 | if r1 == r10 goto l0_%=; \ |
151 | l0_%=: r0 = 0; \ |
152 | exit; \ |
153 | " ::: __clobber_all); |
154 | } |
155 | |
156 | SEC("tracepoint" ) |
157 | __description("unpriv: check that printk is disallowed" ) |
158 | __success |
159 | __naked void check_that_printk_is_disallowed(void) |
160 | { |
161 | asm volatile (" \ |
162 | r1 = 0; \ |
163 | *(u64*)(r10 - 8) = r1; \ |
164 | r1 = r10; \ |
165 | r1 += -8; \ |
166 | r2 = 8; \ |
167 | r3 = r1; \ |
168 | call %[bpf_trace_printk]; \ |
169 | r0 = 0; \ |
170 | exit; \ |
171 | " : |
172 | : __imm(bpf_trace_printk) |
173 | : __clobber_all); |
174 | } |
175 | |
176 | SEC("socket" ) |
177 | __description("unpriv: pass pointer to helper function" ) |
178 | __success __failure_unpriv __msg_unpriv("R4 leaks addr" ) |
179 | __retval(0) |
180 | __naked void pass_pointer_to_helper_function(void) |
181 | { |
182 | asm volatile (" \ |
183 | r1 = 0; \ |
184 | *(u64*)(r10 - 8) = r1; \ |
185 | r2 = r10; \ |
186 | r2 += -8; \ |
187 | r1 = %[map_hash_8b] ll; \ |
188 | r3 = r2; \ |
189 | r4 = r2; \ |
190 | call %[bpf_map_update_elem]; \ |
191 | r0 = 0; \ |
192 | exit; \ |
193 | " : |
194 | : __imm(bpf_map_update_elem), |
195 | __imm_addr(map_hash_8b) |
196 | : __clobber_all); |
197 | } |
198 | |
199 | SEC("socket" ) |
200 | __description("unpriv: indirectly pass pointer on stack to helper function" ) |
201 | __success __failure_unpriv |
202 | __msg_unpriv("invalid indirect read from stack R2 off -8+0 size 8" ) |
203 | __retval(0) |
204 | __naked void on_stack_to_helper_function(void) |
205 | { |
206 | asm volatile (" \ |
207 | *(u64*)(r10 - 8) = r10; \ |
208 | r2 = r10; \ |
209 | r2 += -8; \ |
210 | r1 = %[map_hash_8b] ll; \ |
211 | call %[bpf_map_lookup_elem]; \ |
212 | r0 = 0; \ |
213 | exit; \ |
214 | " : |
215 | : __imm(bpf_map_lookup_elem), |
216 | __imm_addr(map_hash_8b) |
217 | : __clobber_all); |
218 | } |
219 | |
220 | SEC("socket" ) |
221 | __description("unpriv: mangle pointer on stack 1" ) |
222 | __success __failure_unpriv __msg_unpriv("attempt to corrupt spilled" ) |
223 | __retval(0) |
224 | __naked void mangle_pointer_on_stack_1(void) |
225 | { |
226 | asm volatile (" \ |
227 | *(u64*)(r10 - 8) = r10; \ |
228 | r0 = 0; \ |
229 | *(u32*)(r10 - 8) = r0; \ |
230 | r0 = 0; \ |
231 | exit; \ |
232 | " ::: __clobber_all); |
233 | } |
234 | |
235 | SEC("socket" ) |
236 | __description("unpriv: mangle pointer on stack 2" ) |
237 | __success __failure_unpriv __msg_unpriv("attempt to corrupt spilled" ) |
238 | __retval(0) |
239 | __naked void mangle_pointer_on_stack_2(void) |
240 | { |
241 | asm volatile (" \ |
242 | *(u64*)(r10 - 8) = r10; \ |
243 | r0 = 0; \ |
244 | *(u8*)(r10 - 1) = r0; \ |
245 | r0 = 0; \ |
246 | exit; \ |
247 | " ::: __clobber_all); |
248 | } |
249 | |
250 | SEC("socket" ) |
251 | __description("unpriv: read pointer from stack in small chunks" ) |
252 | __failure __msg("invalid size" ) |
253 | __failure_unpriv |
254 | __naked void from_stack_in_small_chunks(void) |
255 | { |
256 | asm volatile (" \ |
257 | *(u64*)(r10 - 8) = r10; \ |
258 | r0 = *(u32*)(r10 - 8); \ |
259 | r0 = 0; \ |
260 | exit; \ |
261 | " ::: __clobber_all); |
262 | } |
263 | |
264 | SEC("socket" ) |
265 | __description("unpriv: write pointer into ctx" ) |
266 | __failure __msg("invalid bpf_context access" ) |
267 | __failure_unpriv __msg_unpriv("R1 leaks addr" ) |
268 | __naked void unpriv_write_pointer_into_ctx(void) |
269 | { |
270 | asm volatile (" \ |
271 | *(u64*)(r1 + 0) = r1; \ |
272 | r0 = 0; \ |
273 | exit; \ |
274 | " ::: __clobber_all); |
275 | } |
276 | |
277 | SEC("socket" ) |
278 | __description("unpriv: spill/fill of ctx" ) |
279 | __success __success_unpriv __retval(0) |
280 | __naked void unpriv_spill_fill_of_ctx(void) |
281 | { |
282 | asm volatile (" \ |
283 | r6 = r10; \ |
284 | r6 += -8; \ |
285 | *(u64*)(r6 + 0) = r1; \ |
286 | r1 = *(u64*)(r6 + 0); \ |
287 | r0 = 0; \ |
288 | exit; \ |
289 | " ::: __clobber_all); |
290 | } |
291 | |
292 | SEC("tc" ) |
293 | __description("unpriv: spill/fill of ctx 2" ) |
294 | __success __retval(0) |
295 | __naked void spill_fill_of_ctx_2(void) |
296 | { |
297 | asm volatile (" \ |
298 | r6 = r10; \ |
299 | r6 += -8; \ |
300 | *(u64*)(r6 + 0) = r1; \ |
301 | r1 = *(u64*)(r6 + 0); \ |
302 | call %[bpf_get_hash_recalc]; \ |
303 | r0 = 0; \ |
304 | exit; \ |
305 | " : |
306 | : __imm(bpf_get_hash_recalc) |
307 | : __clobber_all); |
308 | } |
309 | |
310 | SEC("tc" ) |
311 | __description("unpriv: spill/fill of ctx 3" ) |
312 | __failure __msg("R1 type=fp expected=ctx" ) |
313 | __naked void spill_fill_of_ctx_3(void) |
314 | { |
315 | asm volatile (" \ |
316 | r6 = r10; \ |
317 | r6 += -8; \ |
318 | *(u64*)(r6 + 0) = r1; \ |
319 | *(u64*)(r6 + 0) = r10; \ |
320 | r1 = *(u64*)(r6 + 0); \ |
321 | call %[bpf_get_hash_recalc]; \ |
322 | exit; \ |
323 | " : |
324 | : __imm(bpf_get_hash_recalc) |
325 | : __clobber_all); |
326 | } |
327 | |
328 | SEC("tc" ) |
329 | __description("unpriv: spill/fill of ctx 4" ) |
330 | __failure __msg("R1 type=scalar expected=ctx" ) |
331 | __naked void spill_fill_of_ctx_4(void) |
332 | { |
333 | asm volatile (" \ |
334 | r6 = r10; \ |
335 | r6 += -8; \ |
336 | *(u64*)(r6 + 0) = r1; \ |
337 | r0 = 1; \ |
338 | lock *(u64 *)(r10 - 8) += r0; \ |
339 | r1 = *(u64*)(r6 + 0); \ |
340 | call %[bpf_get_hash_recalc]; \ |
341 | exit; \ |
342 | " : |
343 | : __imm(bpf_get_hash_recalc) |
344 | : __clobber_all); |
345 | } |
346 | |
347 | SEC("tc" ) |
348 | __description("unpriv: spill/fill of different pointers stx" ) |
349 | __failure __msg("same insn cannot be used with different pointers" ) |
350 | __naked void fill_of_different_pointers_stx(void) |
351 | { |
352 | asm volatile (" \ |
353 | r3 = 42; \ |
354 | r6 = r10; \ |
355 | r6 += -8; \ |
356 | if r1 == 0 goto l0_%=; \ |
357 | r2 = r10; \ |
358 | r2 += -16; \ |
359 | *(u64*)(r6 + 0) = r2; \ |
360 | l0_%=: if r1 != 0 goto l1_%=; \ |
361 | *(u64*)(r6 + 0) = r1; \ |
362 | l1_%=: r1 = *(u64*)(r6 + 0); \ |
363 | *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ |
364 | r0 = 0; \ |
365 | exit; \ |
366 | " : |
367 | : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) |
368 | : __clobber_all); |
369 | } |
370 | |
371 | /* Same as above, but use BPF_ST_MEM to save 42 |
372 | * instead of BPF_STX_MEM. |
373 | */ |
374 | SEC("tc" ) |
375 | __description("unpriv: spill/fill of different pointers st" ) |
376 | __failure __msg("same insn cannot be used with different pointers" ) |
377 | __naked void fill_of_different_pointers_st(void) |
378 | { |
379 | asm volatile (" \ |
380 | r6 = r10; \ |
381 | r6 += -8; \ |
382 | if r1 == 0 goto l0_%=; \ |
383 | r2 = r10; \ |
384 | r2 += -16; \ |
385 | *(u64*)(r6 + 0) = r2; \ |
386 | l0_%=: if r1 != 0 goto l1_%=; \ |
387 | *(u64*)(r6 + 0) = r1; \ |
388 | l1_%=: r1 = *(u64*)(r6 + 0); \ |
389 | .8byte %[st_mem]; \ |
390 | r0 = 0; \ |
391 | exit; \ |
392 | " : |
393 | : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), |
394 | __imm_insn(st_mem, |
395 | BPF_ST_MEM(BPF_W, BPF_REG_1, offsetof(struct __sk_buff, mark), 42)) |
396 | : __clobber_all); |
397 | } |
398 | |
399 | SEC("tc" ) |
400 | __description("unpriv: spill/fill of different pointers stx - ctx and sock" ) |
401 | __failure __msg("type=ctx expected=sock" ) |
402 | __naked void pointers_stx_ctx_and_sock(void) |
403 | { |
404 | asm volatile (" \ |
405 | r8 = r1; \ |
406 | /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ |
407 | " BPF_SK_LOOKUP(bpf_sk_lookup_tcp) |
408 | " r2 = r0; \ |
409 | /* u64 foo; */ \ |
410 | /* void *target = &foo; */ \ |
411 | r6 = r10; \ |
412 | r6 += -8; \ |
413 | r1 = r8; \ |
414 | /* if (skb == NULL) *target = sock; */ \ |
415 | if r1 == 0 goto l0_%=; \ |
416 | *(u64*)(r6 + 0) = r2; \ |
417 | l0_%=: /* else *target = skb; */ \ |
418 | if r1 != 0 goto l1_%=; \ |
419 | *(u64*)(r6 + 0) = r1; \ |
420 | l1_%=: /* struct __sk_buff *skb = *target; */ \ |
421 | r1 = *(u64*)(r6 + 0); \ |
422 | /* skb->mark = 42; */ \ |
423 | r3 = 42; \ |
424 | *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ |
425 | /* if (sk) bpf_sk_release(sk) */ \ |
426 | if r1 == 0 goto l2_%=; \ |
427 | call %[bpf_sk_release]; \ |
428 | l2_%=: r0 = 0; \ |
429 | exit; \ |
430 | " : |
431 | : __imm(bpf_sk_lookup_tcp), |
432 | __imm(bpf_sk_release), |
433 | __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), |
434 | __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) |
435 | : __clobber_all); |
436 | } |
437 | |
438 | SEC("tc" ) |
439 | __description("unpriv: spill/fill of different pointers stx - leak sock" ) |
440 | __failure |
441 | //.errstr = "same insn cannot be used with different pointers", |
442 | __msg("Unreleased reference" ) |
443 | __naked void different_pointers_stx_leak_sock(void) |
444 | { |
445 | asm volatile (" \ |
446 | r8 = r1; \ |
447 | /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ |
448 | " BPF_SK_LOOKUP(bpf_sk_lookup_tcp) |
449 | " r2 = r0; \ |
450 | /* u64 foo; */ \ |
451 | /* void *target = &foo; */ \ |
452 | r6 = r10; \ |
453 | r6 += -8; \ |
454 | r1 = r8; \ |
455 | /* if (skb == NULL) *target = sock; */ \ |
456 | if r1 == 0 goto l0_%=; \ |
457 | *(u64*)(r6 + 0) = r2; \ |
458 | l0_%=: /* else *target = skb; */ \ |
459 | if r1 != 0 goto l1_%=; \ |
460 | *(u64*)(r6 + 0) = r1; \ |
461 | l1_%=: /* struct __sk_buff *skb = *target; */ \ |
462 | r1 = *(u64*)(r6 + 0); \ |
463 | /* skb->mark = 42; */ \ |
464 | r3 = 42; \ |
465 | *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ |
466 | exit; \ |
467 | " : |
468 | : __imm(bpf_sk_lookup_tcp), |
469 | __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), |
470 | __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) |
471 | : __clobber_all); |
472 | } |
473 | |
474 | SEC("tc" ) |
475 | __description("unpriv: spill/fill of different pointers stx - sock and ctx (read)" ) |
476 | __failure __msg("same insn cannot be used with different pointers" ) |
477 | __naked void stx_sock_and_ctx_read(void) |
478 | { |
479 | asm volatile (" \ |
480 | r8 = r1; \ |
481 | /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ |
482 | " BPF_SK_LOOKUP(bpf_sk_lookup_tcp) |
483 | " r2 = r0; \ |
484 | /* u64 foo; */ \ |
485 | /* void *target = &foo; */ \ |
486 | r6 = r10; \ |
487 | r6 += -8; \ |
488 | r1 = r8; \ |
489 | /* if (skb) *target = skb */ \ |
490 | if r1 == 0 goto l0_%=; \ |
491 | *(u64*)(r6 + 0) = r1; \ |
492 | l0_%=: /* else *target = sock */ \ |
493 | if r1 != 0 goto l1_%=; \ |
494 | *(u64*)(r6 + 0) = r2; \ |
495 | l1_%=: /* struct bpf_sock *sk = *target; */ \ |
496 | r1 = *(u64*)(r6 + 0); \ |
497 | /* if (sk) u32 foo = sk->mark; bpf_sk_release(sk); */\ |
498 | if r1 == 0 goto l2_%=; \ |
499 | r3 = *(u32*)(r1 + %[bpf_sock_mark]); \ |
500 | call %[bpf_sk_release]; \ |
501 | l2_%=: r0 = 0; \ |
502 | exit; \ |
503 | " : |
504 | : __imm(bpf_sk_lookup_tcp), |
505 | __imm(bpf_sk_release), |
506 | __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)), |
507 | __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) |
508 | : __clobber_all); |
509 | } |
510 | |
511 | SEC("tc" ) |
512 | __description("unpriv: spill/fill of different pointers stx - sock and ctx (write)" ) |
513 | __failure |
514 | //.errstr = "same insn cannot be used with different pointers", |
515 | __msg("cannot write into sock" ) |
516 | __naked void stx_sock_and_ctx_write(void) |
517 | { |
518 | asm volatile (" \ |
519 | r8 = r1; \ |
520 | /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ |
521 | " BPF_SK_LOOKUP(bpf_sk_lookup_tcp) |
522 | " r2 = r0; \ |
523 | /* u64 foo; */ \ |
524 | /* void *target = &foo; */ \ |
525 | r6 = r10; \ |
526 | r6 += -8; \ |
527 | r1 = r8; \ |
528 | /* if (skb) *target = skb */ \ |
529 | if r1 == 0 goto l0_%=; \ |
530 | *(u64*)(r6 + 0) = r1; \ |
531 | l0_%=: /* else *target = sock */ \ |
532 | if r1 != 0 goto l1_%=; \ |
533 | *(u64*)(r6 + 0) = r2; \ |
534 | l1_%=: /* struct bpf_sock *sk = *target; */ \ |
535 | r1 = *(u64*)(r6 + 0); \ |
536 | /* if (sk) sk->mark = 42; bpf_sk_release(sk); */\ |
537 | if r1 == 0 goto l2_%=; \ |
538 | r3 = 42; \ |
539 | *(u32*)(r1 + %[bpf_sock_mark]) = r3; \ |
540 | call %[bpf_sk_release]; \ |
541 | l2_%=: r0 = 0; \ |
542 | exit; \ |
543 | " : |
544 | : __imm(bpf_sk_lookup_tcp), |
545 | __imm(bpf_sk_release), |
546 | __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)), |
547 | __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) |
548 | : __clobber_all); |
549 | } |
550 | |
551 | SEC("socket" ) |
552 | __description("unpriv: write pointer into map elem value" ) |
553 | __success __failure_unpriv __msg_unpriv("R0 leaks addr" ) |
554 | __retval(0) |
555 | __naked void pointer_into_map_elem_value(void) |
556 | { |
557 | asm volatile (" \ |
558 | r1 = 0; \ |
559 | *(u64*)(r10 - 8) = r1; \ |
560 | r2 = r10; \ |
561 | r2 += -8; \ |
562 | r1 = %[map_hash_8b] ll; \ |
563 | call %[bpf_map_lookup_elem]; \ |
564 | if r0 == 0 goto l0_%=; \ |
565 | *(u64*)(r0 + 0) = r0; \ |
566 | l0_%=: exit; \ |
567 | " : |
568 | : __imm(bpf_map_lookup_elem), |
569 | __imm_addr(map_hash_8b) |
570 | : __clobber_all); |
571 | } |
572 | |
573 | SEC("socket" ) |
574 | __description("alu32: mov u32 const" ) |
575 | __success __failure_unpriv __msg_unpriv("R7 invalid mem access 'scalar'" ) |
576 | __retval(0) |
577 | __naked void alu32_mov_u32_const(void) |
578 | { |
579 | asm volatile (" \ |
580 | w7 = 0; \ |
581 | w7 &= 1; \ |
582 | w0 = w7; \ |
583 | if r0 == 0 goto l0_%=; \ |
584 | r0 = *(u64*)(r7 + 0); \ |
585 | l0_%=: exit; \ |
586 | " ::: __clobber_all); |
587 | } |
588 | |
589 | SEC("socket" ) |
590 | __description("unpriv: partial copy of pointer" ) |
591 | __success __failure_unpriv __msg_unpriv("R10 partial copy" ) |
592 | __retval(0) |
593 | __naked void unpriv_partial_copy_of_pointer(void) |
594 | { |
595 | asm volatile (" \ |
596 | w1 = w10; \ |
597 | r0 = 0; \ |
598 | exit; \ |
599 | " ::: __clobber_all); |
600 | } |
601 | |
602 | SEC("socket" ) |
603 | __description("unpriv: pass pointer to tail_call" ) |
604 | __success __failure_unpriv __msg_unpriv("R3 leaks addr into helper" ) |
605 | __retval(0) |
606 | __naked void pass_pointer_to_tail_call(void) |
607 | { |
608 | asm volatile (" \ |
609 | r3 = r1; \ |
610 | r2 = %[map_prog1_socket] ll; \ |
611 | call %[bpf_tail_call]; \ |
612 | r0 = 0; \ |
613 | exit; \ |
614 | " : |
615 | : __imm(bpf_tail_call), |
616 | __imm_addr(map_prog1_socket) |
617 | : __clobber_all); |
618 | } |
619 | |
620 | SEC("socket" ) |
621 | __description("unpriv: cmp map pointer with zero" ) |
622 | __success __failure_unpriv __msg_unpriv("R1 pointer comparison" ) |
623 | __retval(0) |
624 | __naked void cmp_map_pointer_with_zero(void) |
625 | { |
626 | asm volatile (" \ |
627 | r1 = 0; \ |
628 | r1 = %[map_hash_8b] ll; \ |
629 | if r1 == 0 goto l0_%=; \ |
630 | l0_%=: r0 = 0; \ |
631 | exit; \ |
632 | " : |
633 | : __imm_addr(map_hash_8b) |
634 | : __clobber_all); |
635 | } |
636 | |
637 | SEC("socket" ) |
638 | __description("unpriv: write into frame pointer" ) |
639 | __failure __msg("frame pointer is read only" ) |
640 | __failure_unpriv |
641 | __naked void unpriv_write_into_frame_pointer(void) |
642 | { |
643 | asm volatile (" \ |
644 | r10 = r1; \ |
645 | r0 = 0; \ |
646 | exit; \ |
647 | " ::: __clobber_all); |
648 | } |
649 | |
650 | SEC("socket" ) |
651 | __description("unpriv: spill/fill frame pointer" ) |
652 | __failure __msg("frame pointer is read only" ) |
653 | __failure_unpriv |
654 | __naked void unpriv_spill_fill_frame_pointer(void) |
655 | { |
656 | asm volatile (" \ |
657 | r6 = r10; \ |
658 | r6 += -8; \ |
659 | *(u64*)(r6 + 0) = r10; \ |
660 | r10 = *(u64*)(r6 + 0); \ |
661 | r0 = 0; \ |
662 | exit; \ |
663 | " ::: __clobber_all); |
664 | } |
665 | |
666 | SEC("socket" ) |
667 | __description("unpriv: cmp of frame pointer" ) |
668 | __success __failure_unpriv __msg_unpriv("R10 pointer comparison" ) |
669 | __retval(0) |
670 | __naked void unpriv_cmp_of_frame_pointer(void) |
671 | { |
672 | asm volatile (" \ |
673 | if r10 == 0 goto l0_%=; \ |
674 | l0_%=: r0 = 0; \ |
675 | exit; \ |
676 | " ::: __clobber_all); |
677 | } |
678 | |
679 | SEC("socket" ) |
680 | __description("unpriv: adding of fp, reg" ) |
681 | __success __failure_unpriv |
682 | __msg_unpriv("R1 stack pointer arithmetic goes out of range" ) |
683 | __retval(0) |
684 | __naked void unpriv_adding_of_fp_reg(void) |
685 | { |
686 | asm volatile (" \ |
687 | r0 = 0; \ |
688 | r1 = 0; \ |
689 | r1 += r10; \ |
690 | *(u64*)(r1 - 8) = r0; \ |
691 | exit; \ |
692 | " ::: __clobber_all); |
693 | } |
694 | |
695 | SEC("socket" ) |
696 | __description("unpriv: adding of fp, imm" ) |
697 | __success __failure_unpriv |
698 | __msg_unpriv("R1 stack pointer arithmetic goes out of range" ) |
699 | __retval(0) |
700 | __naked void unpriv_adding_of_fp_imm(void) |
701 | { |
702 | asm volatile (" \ |
703 | r0 = 0; \ |
704 | r1 = r10; \ |
705 | r1 += 0; \ |
706 | *(u64*)(r1 - 8) = r0; \ |
707 | exit; \ |
708 | " ::: __clobber_all); |
709 | } |
710 | |
711 | SEC("socket" ) |
712 | __description("unpriv: cmp of stack pointer" ) |
713 | __success __failure_unpriv __msg_unpriv("R2 pointer comparison" ) |
714 | __retval(0) |
715 | __naked void unpriv_cmp_of_stack_pointer(void) |
716 | { |
717 | asm volatile (" \ |
718 | r2 = r10; \ |
719 | r2 += -8; \ |
720 | if r2 == 0 goto l0_%=; \ |
721 | l0_%=: r0 = 0; \ |
722 | exit; \ |
723 | " ::: __clobber_all); |
724 | } |
725 | |
726 | char _license[] SEC("license" ) = "GPL" ; |
727 | |