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
8SEC("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; \
20l0_%=: 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
28SEC("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; \
40l0_%=: 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
48SEC("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; \
60l0_%=: 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
68SEC("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); \
80l0_%=: 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
88SEC("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); \
100l0_%=: 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
108SEC("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); \
120l0_%=: 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
128SEC("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); \
143l0_%=: 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
151SEC("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
173SEC("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
187SEC("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
201SEC("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
215SEC("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
234char _license[] SEC("license") = "GPL";
235

source code of linux/tools/testing/selftests/bpf/progs/verifier_lwt.c