xref: /linux/tools/testing/selftests/bpf/progs/verifier_basic_stack.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/basic_stack.c */
3 
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7 
8 struct {
9 	__uint(type, BPF_MAP_TYPE_HASH);
10 	__uint(max_entries, 1);
11 	__type(key, long long);
12 	__type(value, long long);
13 } map_hash_8b SEC(".maps");
14 
15 SEC("socket")
16 __description("stack out of bounds")
17 __failure __msg("invalid write to stack")
18 __failure_unpriv
stack_out_of_bounds(void)19 __naked void stack_out_of_bounds(void)
20 {
21 	asm volatile ("					\
22 	r1 = 0;						\
23 	*(u64*)(r10 + 8) = r1;				\
24 	exit;						\
25 "	::: __clobber_all);
26 }
27 
28 SEC("socket")
29 __description("uninitialized stack1")
30 __success __log_level(4)
31 __msg("subprog 0 (uninitialized_stack1) main {{.*}} stack 8")
32 __failure_unpriv __msg_unpriv("invalid read from stack")
uninitialized_stack1(void)33 __naked void uninitialized_stack1(void)
34 {
35 	asm volatile ("					\
36 	r2 = r10;					\
37 	r2 += -8;					\
38 	r1 = %[map_hash_8b] ll;				\
39 	call %[bpf_map_lookup_elem];			\
40 	exit;						\
41 "	:
42 	: __imm(bpf_map_lookup_elem),
43 	  __imm_addr(map_hash_8b)
44 	: __clobber_all);
45 }
46 
47 SEC("socket")
48 __description("uninitialized stack2")
49 __success __log_level(4)
50 __msg("subprog 0 (uninitialized_stack2) main insns_self {{[0-9]+}} insns_total {{[0-9]+}} stack 8")
51 __failure_unpriv __msg_unpriv("invalid read from stack")
uninitialized_stack2(void)52 __naked void uninitialized_stack2(void)
53 {
54 	asm volatile ("					\
55 	r2 = r10;					\
56 	r0 = *(u64*)(r2 - 8);				\
57 	exit;						\
58 "	::: __clobber_all);
59 }
60 
61 SEC("socket")
62 __description("invalid fp arithmetic")
63 __failure __msg("R1 subtraction from stack pointer")
64 __failure_unpriv
invalid_fp_arithmetic(void)65 __naked void invalid_fp_arithmetic(void)
66 {
67 	/* If this gets ever changed, make sure JITs can deal with it. */
68 	asm volatile ("					\
69 	r0 = 0;						\
70 	r1 = r10;					\
71 	r1 -= 8;					\
72 	*(u64*)(r1 + 0) = r0;				\
73 	exit;						\
74 "	::: __clobber_all);
75 }
76 
77 SEC("socket")
78 __description("non-invalid fp arithmetic")
79 __success __success_unpriv __retval(0)
non_invalid_fp_arithmetic(void)80 __naked void non_invalid_fp_arithmetic(void)
81 {
82 	asm volatile ("					\
83 	r0 = 0;						\
84 	*(u64*)(r10 - 8) = r0;				\
85 	exit;						\
86 "	::: __clobber_all);
87 }
88 
89 SEC("socket")
90 __description("misaligned read from stack")
91 __failure __msg("misaligned stack access")
92 __failure_unpriv
misaligned_read_from_stack(void)93 __naked void misaligned_read_from_stack(void)
94 {
95 	asm volatile ("					\
96 	r2 = r10;					\
97 	r0 = *(u64*)(r2 - 4);				\
98 	exit;						\
99 "	::: __clobber_all);
100 }
101 
102 SEC("socket")
103 __description("stack pointer arithmetic preserves frame number")
104 __failure __msg("R7 invalid mem access 'scalar'")
stack_ptr_arith_preserves_frameno(void)105 __naked void stack_ptr_arith_preserves_frameno(void)
106 {
107 	asm volatile ("\
108 		r3 = 0;						\
109 		*(u64 *)(r10 - 8) = r3;			\
110 		r1 = %[map_hash_8b] ll;			\
111 		r2 = r10;					\
112 		r2 += -8;					\
113 		call %[bpf_map_lookup_elem];		\
114 		if r0 != 0 goto +2;			\
115 		r0 = 0;						\
116 		exit;						\
117 		r1 = r0;					\
118 		r2 = 0;						\
119 		r3 = 0;						\
120 		call stack_ptr_arith_preserves_frameno_subprog;\
121 		r0 = 0;						\
122 		exit;						\
123 	":
124 	: __imm(bpf_map_lookup_elem),
125 	  __imm_addr(map_hash_8b)
126 	: __clobber_all);
127 }
128 
stack_ptr_arith_preserves_frameno_subprog(void)129 static __used __naked void stack_ptr_arith_preserves_frameno_subprog(void)
130 {
131 	asm volatile ("\
132 		*(u64 *)(r10 - 8) = r1;			\
133 		r6 = -8;					\
134 		r6 += r10;					\
135 		*(u64 *)(r6 + 0) = r2;			\
136 		r7 = *(u64 *)(r10 - 8);			\
137 		*(u64 *)(r7 + 0) = r3;			\
138 		r0 = 0;						\
139 		exit;						\
140 	"::: __clobber_all);
141 }
142 
143 char _license[] SEC("license") = "GPL";
144