selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / verifier_unpriv.c
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";