selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / verifier_lwt.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/lwt.c */
3
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7
8 SEC("lwt_in")
9 __description("invalid direct packet write for LWT_IN")
10 __failure __msg("cannot write into packet")
11 __naked void packet_write_for_lwt_in(void)
12 {
13         asm volatile ("                                 \
14         r2 = *(u32*)(r1 + %[__sk_buff_data]);           \
15         r3 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
16         r0 = r2;                                        \
17         r0 += 8;                                        \
18         if r0 > r3 goto l0_%=;                          \
19         *(u8*)(r2 + 0) = r2;                            \
20 l0_%=:  r0 = 0;                                         \
21         exit;                                           \
22 "       :
23         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
24           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
25         : __clobber_all);
26 }
27
28 SEC("lwt_out")
29 __description("invalid direct packet write for LWT_OUT")
30 __failure __msg("cannot write into packet")
31 __naked void packet_write_for_lwt_out(void)
32 {
33         asm volatile ("                                 \
34         r2 = *(u32*)(r1 + %[__sk_buff_data]);           \
35         r3 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
36         r0 = r2;                                        \
37         r0 += 8;                                        \
38         if r0 > r3 goto l0_%=;                          \
39         *(u8*)(r2 + 0) = r2;                            \
40 l0_%=:  r0 = 0;                                         \
41         exit;                                           \
42 "       :
43         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
44           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
45         : __clobber_all);
46 }
47
48 SEC("lwt_xmit")
49 __description("direct packet write for LWT_XMIT")
50 __success __retval(0)
51 __naked void packet_write_for_lwt_xmit(void)
52 {
53         asm volatile ("                                 \
54         r2 = *(u32*)(r1 + %[__sk_buff_data]);           \
55         r3 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
56         r0 = r2;                                        \
57         r0 += 8;                                        \
58         if r0 > r3 goto l0_%=;                          \
59         *(u8*)(r2 + 0) = r2;                            \
60 l0_%=:  r0 = 0;                                         \
61         exit;                                           \
62 "       :
63         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
64           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
65         : __clobber_all);
66 }
67
68 SEC("lwt_in")
69 __description("direct packet read for LWT_IN")
70 __success __retval(0)
71 __naked void packet_read_for_lwt_in(void)
72 {
73         asm volatile ("                                 \
74         r2 = *(u32*)(r1 + %[__sk_buff_data]);           \
75         r3 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
76         r0 = r2;                                        \
77         r0 += 8;                                        \
78         if r0 > r3 goto l0_%=;                          \
79         r0 = *(u8*)(r2 + 0);                            \
80 l0_%=:  r0 = 0;                                         \
81         exit;                                           \
82 "       :
83         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
84           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
85         : __clobber_all);
86 }
87
88 SEC("lwt_out")
89 __description("direct packet read for LWT_OUT")
90 __success __retval(0)
91 __naked void packet_read_for_lwt_out(void)
92 {
93         asm volatile ("                                 \
94         r2 = *(u32*)(r1 + %[__sk_buff_data]);           \
95         r3 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
96         r0 = r2;                                        \
97         r0 += 8;                                        \
98         if r0 > r3 goto l0_%=;                          \
99         r0 = *(u8*)(r2 + 0);                            \
100 l0_%=:  r0 = 0;                                         \
101         exit;                                           \
102 "       :
103         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
104           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
105         : __clobber_all);
106 }
107
108 SEC("lwt_xmit")
109 __description("direct packet read for LWT_XMIT")
110 __success __retval(0)
111 __naked void packet_read_for_lwt_xmit(void)
112 {
113         asm volatile ("                                 \
114         r2 = *(u32*)(r1 + %[__sk_buff_data]);           \
115         r3 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
116         r0 = r2;                                        \
117         r0 += 8;                                        \
118         if r0 > r3 goto l0_%=;                          \
119         r0 = *(u8*)(r2 + 0);                            \
120 l0_%=:  r0 = 0;                                         \
121         exit;                                           \
122 "       :
123         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
124           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
125         : __clobber_all);
126 }
127
128 SEC("lwt_xmit")
129 __description("overlapping checks for direct packet access")
130 __success __retval(0)
131 __naked void checks_for_direct_packet_access(void)
132 {
133         asm volatile ("                                 \
134         r2 = *(u32*)(r1 + %[__sk_buff_data]);           \
135         r3 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
136         r0 = r2;                                        \
137         r0 += 8;                                        \
138         if r0 > r3 goto l0_%=;                          \
139         r1 = r2;                                        \
140         r1 += 6;                                        \
141         if r1 > r3 goto l0_%=;                          \
142         r0 = *(u16*)(r2 + 6);                           \
143 l0_%=:  r0 = 0;                                         \
144         exit;                                           \
145 "       :
146         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
147           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
148         : __clobber_all);
149 }
150
151 SEC("lwt_xmit")
152 __description("make headroom for LWT_XMIT")
153 __success __retval(0)
154 __naked void make_headroom_for_lwt_xmit(void)
155 {
156         asm volatile ("                                 \
157         r6 = r1;                                        \
158         r2 = 34;                                        \
159         r3 = 0;                                         \
160         call %[bpf_skb_change_head];                    \
161         /* split for s390 to succeed */                 \
162         r1 = r6;                                        \
163         r2 = 42;                                        \
164         r3 = 0;                                         \
165         call %[bpf_skb_change_head];                    \
166         r0 = 0;                                         \
167         exit;                                           \
168 "       :
169         : __imm(bpf_skb_change_head)
170         : __clobber_all);
171 }
172
173 SEC("socket")
174 __description("invalid access of tc_classid for LWT_IN")
175 __failure __msg("invalid bpf_context access")
176 __failure_unpriv
177 __naked void tc_classid_for_lwt_in(void)
178 {
179         asm volatile ("                                 \
180         r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]);     \
181         exit;                                           \
182 "       :
183         : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
184         : __clobber_all);
185 }
186
187 SEC("socket")
188 __description("invalid access of tc_classid for LWT_OUT")
189 __failure __msg("invalid bpf_context access")
190 __failure_unpriv
191 __naked void tc_classid_for_lwt_out(void)
192 {
193         asm volatile ("                                 \
194         r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]);     \
195         exit;                                           \
196 "       :
197         : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
198         : __clobber_all);
199 }
200
201 SEC("socket")
202 __description("invalid access of tc_classid for LWT_XMIT")
203 __failure __msg("invalid bpf_context access")
204 __failure_unpriv
205 __naked void tc_classid_for_lwt_xmit(void)
206 {
207         asm volatile ("                                 \
208         r0 = *(u32*)(r1 + %[__sk_buff_tc_classid]);     \
209         exit;                                           \
210 "       :
211         : __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
212         : __clobber_all);
213 }
214
215 SEC("lwt_in")
216 __description("check skb->tc_classid half load not permitted for lwt prog")
217 __failure __msg("invalid bpf_context access")
218 __naked void not_permitted_for_lwt_prog(void)
219 {
220         asm volatile (
221         "r0 = 0;"
222 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
223         "r0 = *(u16*)(r1 + %[__sk_buff_tc_classid]);"
224 #else
225         "r0 = *(u16*)(r1 + %[__imm_0]);"
226 #endif
227         "exit;"
228         :
229         : __imm_const(__imm_0, offsetof(struct __sk_buff, tc_classid) + 2),
230           __imm_const(__sk_buff_tc_classid, offsetof(struct __sk_buff, tc_classid))
231         : __clobber_all);
232 }
233
234 char _license[] SEC("license") = "GPL";