1dec02028SEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2dec02028SEduard Zingerman 
3dec02028SEduard Zingerman #include <linux/bpf.h>
4dec02028SEduard Zingerman #include <bpf/bpf_helpers.h>
5dec02028SEduard Zingerman #include "bpf_misc.h"
6dec02028SEduard Zingerman 
7dec02028SEduard Zingerman /* Check that precision marks propagate through scalar IDs.
8dec02028SEduard Zingerman  * Registers r{0,1,2} have the same scalar ID at the moment when r0 is
9dec02028SEduard Zingerman  * marked to be precise, this mark is immediately propagated to r{1,2}.
10dec02028SEduard Zingerman  */
11dec02028SEduard Zingerman SEC("socket")
12dec02028SEduard Zingerman __success __log_level(2)
13dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 4: (bf) r3 = r10")
14dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
15dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
16dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
17dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)18dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
19dec02028SEduard Zingerman __naked void precision_same_state(void)
20dec02028SEduard Zingerman {
21dec02028SEduard Zingerman 	asm volatile (
22dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
23dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
24dec02028SEduard Zingerman 	"r0 &= 0xff;"
25dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
26dec02028SEduard Zingerman 	"r1 = r0;"
27dec02028SEduard Zingerman 	"r2 = r0;"
28dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
29dec02028SEduard Zingerman 	 * precise as well because of shared IDs
30dec02028SEduard Zingerman 	 */
31dec02028SEduard Zingerman 	"r3 = r10;"
32dec02028SEduard Zingerman 	"r3 += r0;"
33dec02028SEduard Zingerman 	"r0 = 0;"
34dec02028SEduard Zingerman 	"exit;"
35dec02028SEduard Zingerman 	:
36dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
37dec02028SEduard Zingerman 	: __clobber_all);
38dec02028SEduard Zingerman }
39dec02028SEduard Zingerman 
40dec02028SEduard Zingerman /* Same as precision_same_state, but mark propagates through state /
41dec02028SEduard Zingerman  * parent state boundary.
42dec02028SEduard Zingerman  */
43dec02028SEduard Zingerman SEC("socket")
44dec02028SEduard Zingerman __success __log_level(2)
45dec02028SEduard Zingerman __msg("frame0: last_idx 6 first_idx 5 subseq_idx -1")
46dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 5: (bf) r3 = r10")
47dec02028SEduard Zingerman __msg("frame0: parent state regs=r0,r1,r2 stack=:")
48dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 4: (05) goto pc+0")
49dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
50dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
51dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
52dec02028SEduard Zingerman __msg("frame0: parent state regs=r0 stack=:")
53dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)54dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
55dec02028SEduard Zingerman __naked void precision_cross_state(void)
56dec02028SEduard Zingerman {
57dec02028SEduard Zingerman 	asm volatile (
58dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
59dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
60dec02028SEduard Zingerman 	"r0 &= 0xff;"
61dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
62dec02028SEduard Zingerman 	"r1 = r0;"
63dec02028SEduard Zingerman 	"r2 = r0;"
64dec02028SEduard Zingerman 	/* force checkpoint */
65dec02028SEduard Zingerman 	"goto +0;"
66dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
67dec02028SEduard Zingerman 	 * precise as well because of shared IDs
68dec02028SEduard Zingerman 	 */
69dec02028SEduard Zingerman 	"r3 = r10;"
70dec02028SEduard Zingerman 	"r3 += r0;"
71dec02028SEduard Zingerman 	"r0 = 0;"
72dec02028SEduard Zingerman 	"exit;"
73dec02028SEduard Zingerman 	:
74dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
75dec02028SEduard Zingerman 	: __clobber_all);
76dec02028SEduard Zingerman }
77dec02028SEduard Zingerman 
78dec02028SEduard Zingerman /* Same as precision_same_state, but break one of the
79dec02028SEduard Zingerman  * links, note that r1 is absent from regs=... in __msg below.
80dec02028SEduard Zingerman  */
81dec02028SEduard Zingerman SEC("socket")
82dec02028SEduard Zingerman __success __log_level(2)
83dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 5: (bf) r3 = r10")
84dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 4: (b7) r1 = 0")
85dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 3: (bf) r2 = r0")
86dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 2: (bf) r1 = r0")
87dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
88dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)89dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
90dec02028SEduard Zingerman __naked void precision_same_state_broken_link(void)
91dec02028SEduard Zingerman {
92dec02028SEduard Zingerman 	asm volatile (
93dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
94dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
95dec02028SEduard Zingerman 	"r0 &= 0xff;"
96dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
97dec02028SEduard Zingerman 	"r1 = r0;"
98dec02028SEduard Zingerman 	"r2 = r0;"
99dec02028SEduard Zingerman 	/* break link for r1, this is the only line that differs
100dec02028SEduard Zingerman 	 * compared to the previous test
101dec02028SEduard Zingerman 	 */
102dec02028SEduard Zingerman 	"r1 = 0;"
103dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
104dec02028SEduard Zingerman 	 * precise as well because of shared IDs
105dec02028SEduard Zingerman 	 */
106dec02028SEduard Zingerman 	"r3 = r10;"
107dec02028SEduard Zingerman 	"r3 += r0;"
108dec02028SEduard Zingerman 	"r0 = 0;"
109dec02028SEduard Zingerman 	"exit;"
110dec02028SEduard Zingerman 	:
111dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
112dec02028SEduard Zingerman 	: __clobber_all);
113dec02028SEduard Zingerman }
114dec02028SEduard Zingerman 
115dec02028SEduard Zingerman /* Same as precision_same_state_broken_link, but with state /
116dec02028SEduard Zingerman  * parent state boundary.
117dec02028SEduard Zingerman  */
118dec02028SEduard Zingerman SEC("socket")
119dec02028SEduard Zingerman __success __log_level(2)
120dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 6: (bf) r3 = r10")
121dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 5: (b7) r1 = 0")
122dec02028SEduard Zingerman __msg("frame0: parent state regs=r0,r2 stack=:")
123dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 4: (05) goto pc+0")
124dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
125dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
126dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
127dec02028SEduard Zingerman __msg("frame0: parent state regs=r0 stack=:")
128dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)129dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
130dec02028SEduard Zingerman __naked void precision_cross_state_broken_link(void)
131dec02028SEduard Zingerman {
132dec02028SEduard Zingerman 	asm volatile (
133dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
134dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
135dec02028SEduard Zingerman 	"r0 &= 0xff;"
136dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
137dec02028SEduard Zingerman 	"r1 = r0;"
138dec02028SEduard Zingerman 	"r2 = r0;"
139dec02028SEduard Zingerman 	/* force checkpoint, although link between r1 and r{0,2} is
140dec02028SEduard Zingerman 	 * broken by the next statement current precision tracking
141dec02028SEduard Zingerman 	 * algorithm can't react to it and propagates mark for r1 to
142dec02028SEduard Zingerman 	 * the parent state.
143dec02028SEduard Zingerman 	 */
144dec02028SEduard Zingerman 	"goto +0;"
145dec02028SEduard Zingerman 	/* break link for r1, this is the only line that differs
146dec02028SEduard Zingerman 	 * compared to precision_cross_state()
147dec02028SEduard Zingerman 	 */
148dec02028SEduard Zingerman 	"r1 = 0;"
149dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
150dec02028SEduard Zingerman 	 * precise as well because of shared IDs
151dec02028SEduard Zingerman 	 */
152dec02028SEduard Zingerman 	"r3 = r10;"
153dec02028SEduard Zingerman 	"r3 += r0;"
154dec02028SEduard Zingerman 	"r0 = 0;"
155dec02028SEduard Zingerman 	"exit;"
156dec02028SEduard Zingerman 	:
157dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
158dec02028SEduard Zingerman 	: __clobber_all);
159dec02028SEduard Zingerman }
160dec02028SEduard Zingerman 
161dec02028SEduard Zingerman /* Check that precision marks propagate through scalar IDs.
162dec02028SEduard Zingerman  * Use the same scalar ID in multiple stack frames, check that
163dec02028SEduard Zingerman  * precision information is propagated up the call stack.
164dec02028SEduard Zingerman  */
165dec02028SEduard Zingerman SEC("socket")
166dec02028SEduard Zingerman __success __log_level(2)
167dec02028SEduard Zingerman __msg("11: (0f) r2 += r1")
168dec02028SEduard Zingerman /* Current state */
169dec02028SEduard Zingerman __msg("frame2: last_idx 11 first_idx 10 subseq_idx -1")
170dec02028SEduard Zingerman __msg("frame2: regs=r1 stack= before 10: (bf) r2 = r10")
171dec02028SEduard Zingerman __msg("frame2: parent state regs=r1 stack=")
172dec02028SEduard Zingerman /* frame1.r{6,7} are marked because mark_precise_scalar_ids()
173dec02028SEduard Zingerman  * looks for all registers with frame2.r1.id in the current state
174dec02028SEduard Zingerman  */
175dec02028SEduard Zingerman __msg("frame1: parent state regs=r6,r7 stack=")
176dec02028SEduard Zingerman __msg("frame0: parent state regs=r6 stack=")
177dec02028SEduard Zingerman /* Parent state */
178dec02028SEduard Zingerman __msg("frame2: last_idx 8 first_idx 8 subseq_idx 10")
179dec02028SEduard Zingerman __msg("frame2: regs=r1 stack= before 8: (85) call pc+1")
180dec02028SEduard Zingerman /* frame1.r1 is marked because of backtracking of call instruction */
181dec02028SEduard Zingerman __msg("frame1: parent state regs=r1,r6,r7 stack=")
182dec02028SEduard Zingerman __msg("frame0: parent state regs=r6 stack=")
183dec02028SEduard Zingerman /* Parent state */
184dec02028SEduard Zingerman __msg("frame1: last_idx 7 first_idx 6 subseq_idx 8")
185dec02028SEduard Zingerman __msg("frame1: regs=r1,r6,r7 stack= before 7: (bf) r7 = r1")
186dec02028SEduard Zingerman __msg("frame1: regs=r1,r6 stack= before 6: (bf) r6 = r1")
187dec02028SEduard Zingerman __msg("frame1: parent state regs=r1 stack=")
188dec02028SEduard Zingerman __msg("frame0: parent state regs=r6 stack=")
189dec02028SEduard Zingerman /* Parent state */
190dec02028SEduard Zingerman __msg("frame1: last_idx 4 first_idx 4 subseq_idx 6")
191dec02028SEduard Zingerman __msg("frame1: regs=r1 stack= before 4: (85) call pc+1")
192dec02028SEduard Zingerman __msg("frame0: parent state regs=r1,r6 stack=")
193dec02028SEduard Zingerman /* Parent state */
194dec02028SEduard Zingerman __msg("frame0: last_idx 3 first_idx 1 subseq_idx 4")
195dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r6 stack= before 3: (bf) r6 = r0")
196dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
197dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
__flag(BPF_F_TEST_STATE_FREQ)198dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
199dec02028SEduard Zingerman __naked void precision_many_frames(void)
200dec02028SEduard Zingerman {
201dec02028SEduard Zingerman 	asm volatile (
202dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
203dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
204dec02028SEduard Zingerman 	"r0 &= 0xff;"
205dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r6.id */
206dec02028SEduard Zingerman 	"r1 = r0;"
207dec02028SEduard Zingerman 	"r6 = r0;"
208dec02028SEduard Zingerman 	"call precision_many_frames__foo;"
209dec02028SEduard Zingerman 	"exit;"
210dec02028SEduard Zingerman 	:
211dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
212dec02028SEduard Zingerman 	: __clobber_all);
213dec02028SEduard Zingerman }
214dec02028SEduard Zingerman 
215dec02028SEduard Zingerman static __naked __noinline __used
precision_many_frames__foo(void)216dec02028SEduard Zingerman void precision_many_frames__foo(void)
217dec02028SEduard Zingerman {
218dec02028SEduard Zingerman 	asm volatile (
219dec02028SEduard Zingerman 	/* conflate one of the register numbers (r6) with outer frame,
220dec02028SEduard Zingerman 	 * to verify that those are tracked independently
221dec02028SEduard Zingerman 	 */
222dec02028SEduard Zingerman 	"r6 = r1;"
223dec02028SEduard Zingerman 	"r7 = r1;"
224dec02028SEduard Zingerman 	"call precision_many_frames__bar;"
225dec02028SEduard Zingerman 	"exit"
226dec02028SEduard Zingerman 	::: __clobber_all);
227dec02028SEduard Zingerman }
228dec02028SEduard Zingerman 
229dec02028SEduard Zingerman static __naked __noinline __used
precision_many_frames__bar(void)230dec02028SEduard Zingerman void precision_many_frames__bar(void)
231dec02028SEduard Zingerman {
232dec02028SEduard Zingerman 	asm volatile (
233dec02028SEduard Zingerman 	/* force r1 to be precise, this immediately marks:
234dec02028SEduard Zingerman 	 * - bar frame r1
235dec02028SEduard Zingerman 	 * - foo frame r{1,6,7}
236dec02028SEduard Zingerman 	 * - main frame r{1,6}
237dec02028SEduard Zingerman 	 */
238dec02028SEduard Zingerman 	"r2 = r10;"
239dec02028SEduard Zingerman 	"r2 += r1;"
240dec02028SEduard Zingerman 	"r0 = 0;"
241dec02028SEduard Zingerman 	"exit;"
242dec02028SEduard Zingerman 	::: __clobber_all);
243dec02028SEduard Zingerman }
244dec02028SEduard Zingerman 
245dec02028SEduard Zingerman /* Check that scalars with the same IDs are marked precise on stack as
246dec02028SEduard Zingerman  * well as in registers.
247dec02028SEduard Zingerman  */
248dec02028SEduard Zingerman SEC("socket")
249dec02028SEduard Zingerman __success __log_level(2)
250dec02028SEduard Zingerman /* foo frame */
251dec02028SEduard Zingerman __msg("frame1: regs=r1 stack=-8,-16 before 9: (bf) r2 = r10")
252dec02028SEduard Zingerman __msg("frame1: regs=r1 stack=-8,-16 before 8: (7b) *(u64 *)(r10 -16) = r1")
253dec02028SEduard Zingerman __msg("frame1: regs=r1 stack=-8 before 7: (7b) *(u64 *)(r10 -8) = r1")
254dec02028SEduard Zingerman __msg("frame1: regs=r1 stack= before 4: (85) call pc+2")
255dec02028SEduard Zingerman /* main frame */
256dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack=-8 before 3: (7b) *(u64 *)(r10 -8) = r1")
257dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
258dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
__flag(BPF_F_TEST_STATE_FREQ)259dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
260dec02028SEduard Zingerman __naked void precision_stack(void)
261dec02028SEduard Zingerman {
262dec02028SEduard Zingerman 	asm volatile (
263dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
264dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
265dec02028SEduard Zingerman 	"r0 &= 0xff;"
266dec02028SEduard Zingerman 	/* tie r0.id == r1.id == fp[-8].id */
267dec02028SEduard Zingerman 	"r1 = r0;"
268dec02028SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
269dec02028SEduard Zingerman 	"call precision_stack__foo;"
270dec02028SEduard Zingerman 	"r0 = 0;"
271dec02028SEduard Zingerman 	"exit;"
272dec02028SEduard Zingerman 	:
273dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
274dec02028SEduard Zingerman 	: __clobber_all);
275dec02028SEduard Zingerman }
276dec02028SEduard Zingerman 
277dec02028SEduard Zingerman static __naked __noinline __used
precision_stack__foo(void)278dec02028SEduard Zingerman void precision_stack__foo(void)
279dec02028SEduard Zingerman {
280dec02028SEduard Zingerman 	asm volatile (
281dec02028SEduard Zingerman 	/* conflate one of the register numbers (r6) with outer frame,
282dec02028SEduard Zingerman 	 * to verify that those are tracked independently
283dec02028SEduard Zingerman 	 */
284dec02028SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
285dec02028SEduard Zingerman 	"*(u64*)(r10 - 16) = r1;"
286dec02028SEduard Zingerman 	/* force r1 to be precise, this immediately marks:
287dec02028SEduard Zingerman 	 * - foo frame r1,fp{-8,-16}
288dec02028SEduard Zingerman 	 * - main frame r1,fp{-8}
289dec02028SEduard Zingerman 	 */
290dec02028SEduard Zingerman 	"r2 = r10;"
291dec02028SEduard Zingerman 	"r2 += r1;"
292dec02028SEduard Zingerman 	"exit"
293dec02028SEduard Zingerman 	::: __clobber_all);
294dec02028SEduard Zingerman }
295dec02028SEduard Zingerman 
296dec02028SEduard Zingerman /* Use two separate scalar IDs to check that these are propagated
297dec02028SEduard Zingerman  * independently.
298dec02028SEduard Zingerman  */
299dec02028SEduard Zingerman SEC("socket")
300dec02028SEduard Zingerman __success __log_level(2)
301dec02028SEduard Zingerman /* r{6,7} */
302dec02028SEduard Zingerman __msg("11: (0f) r3 += r7")
303dec02028SEduard Zingerman __msg("frame0: regs=r6,r7 stack= before 10: (bf) r3 = r10")
304dec02028SEduard Zingerman /* ... skip some insns ... */
305dec02028SEduard Zingerman __msg("frame0: regs=r6,r7 stack= before 3: (bf) r7 = r0")
306dec02028SEduard Zingerman __msg("frame0: regs=r0,r6 stack= before 2: (bf) r6 = r0")
307dec02028SEduard Zingerman /* r{8,9} */
308dec02028SEduard Zingerman __msg("12: (0f) r3 += r9")
309dec02028SEduard Zingerman __msg("frame0: regs=r8,r9 stack= before 11: (0f) r3 += r7")
310dec02028SEduard Zingerman /* ... skip some insns ... */
311dec02028SEduard Zingerman __msg("frame0: regs=r8,r9 stack= before 7: (bf) r9 = r0")
312dec02028SEduard Zingerman __msg("frame0: regs=r0,r8 stack= before 6: (bf) r8 = r0")
__flag(BPF_F_TEST_STATE_FREQ)313dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
314dec02028SEduard Zingerman __naked void precision_two_ids(void)
315dec02028SEduard Zingerman {
316dec02028SEduard Zingerman 	asm volatile (
317dec02028SEduard Zingerman 	/* r6 = random number up to 0xff
318dec02028SEduard Zingerman 	 * r6.id == r7.id
319dec02028SEduard Zingerman 	 */
320dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
321dec02028SEduard Zingerman 	"r0 &= 0xff;"
322dec02028SEduard Zingerman 	"r6 = r0;"
323dec02028SEduard Zingerman 	"r7 = r0;"
324dec02028SEduard Zingerman 	/* same, but for r{8,9} */
325dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
326dec02028SEduard Zingerman 	"r0 &= 0xff;"
327dec02028SEduard Zingerman 	"r8 = r0;"
328dec02028SEduard Zingerman 	"r9 = r0;"
329dec02028SEduard Zingerman 	/* clear r0 id */
330dec02028SEduard Zingerman 	"r0 = 0;"
331dec02028SEduard Zingerman 	/* force checkpoint */
332dec02028SEduard Zingerman 	"goto +0;"
333dec02028SEduard Zingerman 	"r3 = r10;"
334dec02028SEduard Zingerman 	/* force r7 to be precise, this also marks r6 */
335dec02028SEduard Zingerman 	"r3 += r7;"
336dec02028SEduard Zingerman 	/* force r9 to be precise, this also marks r8 */
337dec02028SEduard Zingerman 	"r3 += r9;"
338dec02028SEduard Zingerman 	"exit;"
339dec02028SEduard Zingerman 	:
340dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
341dec02028SEduard Zingerman 	: __clobber_all);
342dec02028SEduard Zingerman }
343dec02028SEduard Zingerman 
344*18b89265SEduard Zingerman /* Verify that check_ids() is used by regsafe() for scalars.
345*18b89265SEduard Zingerman  *
346*18b89265SEduard Zingerman  * r9 = ... some pointer with range X ...
347*18b89265SEduard Zingerman  * r6 = ... unbound scalar ID=a ...
348*18b89265SEduard Zingerman  * r7 = ... unbound scalar ID=b ...
349*18b89265SEduard Zingerman  * if (r6 > r7) goto +1
350*18b89265SEduard Zingerman  * r7 = r6
351*18b89265SEduard Zingerman  * if (r7 > X) goto exit
352*18b89265SEduard Zingerman  * r9 += r6
353*18b89265SEduard Zingerman  * ... access memory using r9 ...
354*18b89265SEduard Zingerman  *
355*18b89265SEduard Zingerman  * The memory access is safe only if r7 is bounded,
356*18b89265SEduard Zingerman  * which is true for one branch and not true for another.
357*18b89265SEduard Zingerman  */
358*18b89265SEduard Zingerman SEC("socket")
359*18b89265SEduard Zingerman __failure __msg("register with unbounded min value")
__flag(BPF_F_TEST_STATE_FREQ)360*18b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
361*18b89265SEduard Zingerman __naked void check_ids_in_regsafe(void)
362*18b89265SEduard Zingerman {
363*18b89265SEduard Zingerman 	asm volatile (
364*18b89265SEduard Zingerman 	/* Bump allocated stack */
365*18b89265SEduard Zingerman 	"r1 = 0;"
366*18b89265SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
367*18b89265SEduard Zingerman 	/* r9 = pointer to stack */
368*18b89265SEduard Zingerman 	"r9 = r10;"
369*18b89265SEduard Zingerman 	"r9 += -8;"
370*18b89265SEduard Zingerman 	/* r7 = ktime_get_ns() */
371*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
372*18b89265SEduard Zingerman 	"r7 = r0;"
373*18b89265SEduard Zingerman 	/* r6 = ktime_get_ns() */
374*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
375*18b89265SEduard Zingerman 	"r6 = r0;"
376*18b89265SEduard Zingerman 	/* if r6 > r7 is an unpredictable jump */
377*18b89265SEduard Zingerman 	"if r6 > r7 goto l1_%=;"
378*18b89265SEduard Zingerman 	"r7 = r6;"
379*18b89265SEduard Zingerman "l1_%=:"
380*18b89265SEduard Zingerman 	/* if r7 > 4 ...; transfers range to r6 on one execution path
381*18b89265SEduard Zingerman 	 * but does not transfer on another
382*18b89265SEduard Zingerman 	 */
383*18b89265SEduard Zingerman 	"if r7 > 4 goto l2_%=;"
384*18b89265SEduard Zingerman 	/* Access memory at r9[r6], r6 is not always bounded */
385*18b89265SEduard Zingerman 	"r9 += r6;"
386*18b89265SEduard Zingerman 	"r0 = *(u8*)(r9 + 0);"
387*18b89265SEduard Zingerman "l2_%=:"
388*18b89265SEduard Zingerman 	"r0 = 0;"
389*18b89265SEduard Zingerman 	"exit;"
390*18b89265SEduard Zingerman 	:
391*18b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
392*18b89265SEduard Zingerman 	: __clobber_all);
393*18b89265SEduard Zingerman }
394*18b89265SEduard Zingerman 
395*18b89265SEduard Zingerman /* Similar to check_ids_in_regsafe.
396*18b89265SEduard Zingerman  * The l0 could be reached in two states:
397*18b89265SEduard Zingerman  *
398*18b89265SEduard Zingerman  *   (1) r6{.id=A}, r7{.id=A}, r8{.id=B}
399*18b89265SEduard Zingerman  *   (2) r6{.id=B}, r7{.id=A}, r8{.id=B}
400*18b89265SEduard Zingerman  *
401*18b89265SEduard Zingerman  * Where (2) is not safe, as "r7 > 4" check won't propagate range for it.
402*18b89265SEduard Zingerman  * This example would be considered safe without changes to
403*18b89265SEduard Zingerman  * mark_chain_precision() to track scalar values with equal IDs.
404*18b89265SEduard Zingerman  */
405*18b89265SEduard Zingerman SEC("socket")
406*18b89265SEduard Zingerman __failure __msg("register with unbounded min value")
__flag(BPF_F_TEST_STATE_FREQ)407*18b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
408*18b89265SEduard Zingerman __naked void check_ids_in_regsafe_2(void)
409*18b89265SEduard Zingerman {
410*18b89265SEduard Zingerman 	asm volatile (
411*18b89265SEduard Zingerman 	/* Bump allocated stack */
412*18b89265SEduard Zingerman 	"r1 = 0;"
413*18b89265SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
414*18b89265SEduard Zingerman 	/* r9 = pointer to stack */
415*18b89265SEduard Zingerman 	"r9 = r10;"
416*18b89265SEduard Zingerman 	"r9 += -8;"
417*18b89265SEduard Zingerman 	/* r8 = ktime_get_ns() */
418*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
419*18b89265SEduard Zingerman 	"r8 = r0;"
420*18b89265SEduard Zingerman 	/* r7 = ktime_get_ns() */
421*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
422*18b89265SEduard Zingerman 	"r7 = r0;"
423*18b89265SEduard Zingerman 	/* r6 = ktime_get_ns() */
424*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
425*18b89265SEduard Zingerman 	"r6 = r0;"
426*18b89265SEduard Zingerman 	/* scratch .id from r0 */
427*18b89265SEduard Zingerman 	"r0 = 0;"
428*18b89265SEduard Zingerman 	/* if r6 > r7 is an unpredictable jump */
429*18b89265SEduard Zingerman 	"if r6 > r7 goto l1_%=;"
430*18b89265SEduard Zingerman 	/* tie r6 and r7 .id */
431*18b89265SEduard Zingerman 	"r6 = r7;"
432*18b89265SEduard Zingerman "l0_%=:"
433*18b89265SEduard Zingerman 	/* if r7 > 4 exit(0) */
434*18b89265SEduard Zingerman 	"if r7 > 4 goto l2_%=;"
435*18b89265SEduard Zingerman 	/* Access memory at r9[r6] */
436*18b89265SEduard Zingerman 	"r9 += r6;"
437*18b89265SEduard Zingerman 	"r0 = *(u8*)(r9 + 0);"
438*18b89265SEduard Zingerman "l2_%=:"
439*18b89265SEduard Zingerman 	"r0 = 0;"
440*18b89265SEduard Zingerman 	"exit;"
441*18b89265SEduard Zingerman "l1_%=:"
442*18b89265SEduard Zingerman 	/* tie r6 and r8 .id */
443*18b89265SEduard Zingerman 	"r6 = r8;"
444*18b89265SEduard Zingerman 	"goto l0_%=;"
445*18b89265SEduard Zingerman 	:
446*18b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
447*18b89265SEduard Zingerman 	: __clobber_all);
448*18b89265SEduard Zingerman }
449*18b89265SEduard Zingerman 
450*18b89265SEduard Zingerman /* Check that scalar IDs *are not* generated on register to register
451*18b89265SEduard Zingerman  * assignments if source register is a constant.
452*18b89265SEduard Zingerman  *
453*18b89265SEduard Zingerman  * If such IDs *are* generated the 'l1' below would be reached in
454*18b89265SEduard Zingerman  * two states:
455*18b89265SEduard Zingerman  *
456*18b89265SEduard Zingerman  *   (1) r1{.id=A}, r2{.id=A}
457*18b89265SEduard Zingerman  *   (2) r1{.id=C}, r2{.id=C}
458*18b89265SEduard Zingerman  *
459*18b89265SEduard Zingerman  * Thus forcing 'if r1 == r2' verification twice.
460*18b89265SEduard Zingerman  */
461*18b89265SEduard Zingerman SEC("socket")
462*18b89265SEduard Zingerman __success __log_level(2)
463*18b89265SEduard Zingerman __msg("11: (1d) if r3 == r4 goto pc+0")
464*18b89265SEduard Zingerman __msg("frame 0: propagating r3,r4")
465*18b89265SEduard Zingerman __msg("11: safe")
466*18b89265SEduard Zingerman __msg("processed 15 insns")
__flag(BPF_F_TEST_STATE_FREQ)467*18b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
468*18b89265SEduard Zingerman __naked void no_scalar_id_for_const(void)
469*18b89265SEduard Zingerman {
470*18b89265SEduard Zingerman 	asm volatile (
471*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
472*18b89265SEduard Zingerman 	/* unpredictable jump */
473*18b89265SEduard Zingerman 	"if r0 > 7 goto l0_%=;"
474*18b89265SEduard Zingerman 	/* possibly generate same scalar ids for r3 and r4 */
475*18b89265SEduard Zingerman 	"r1 = 0;"
476*18b89265SEduard Zingerman 	"r1 = r1;"
477*18b89265SEduard Zingerman 	"r3 = r1;"
478*18b89265SEduard Zingerman 	"r4 = r1;"
479*18b89265SEduard Zingerman 	"goto l1_%=;"
480*18b89265SEduard Zingerman "l0_%=:"
481*18b89265SEduard Zingerman 	/* possibly generate different scalar ids for r3 and r4 */
482*18b89265SEduard Zingerman 	"r1 = 0;"
483*18b89265SEduard Zingerman 	"r2 = 0;"
484*18b89265SEduard Zingerman 	"r3 = r1;"
485*18b89265SEduard Zingerman 	"r4 = r2;"
486*18b89265SEduard Zingerman "l1_%=:"
487*18b89265SEduard Zingerman 	/* predictable jump, marks r3 and r4 precise */
488*18b89265SEduard Zingerman 	"if r3 == r4 goto +0;"
489*18b89265SEduard Zingerman 	"r0 = 0;"
490*18b89265SEduard Zingerman 	"exit;"
491*18b89265SEduard Zingerman 	:
492*18b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
493*18b89265SEduard Zingerman 	: __clobber_all);
494*18b89265SEduard Zingerman }
495*18b89265SEduard Zingerman 
496*18b89265SEduard Zingerman /* Same as no_scalar_id_for_const() but for 32-bit values */
497*18b89265SEduard Zingerman SEC("socket")
498*18b89265SEduard Zingerman __success __log_level(2)
499*18b89265SEduard Zingerman __msg("11: (1e) if w3 == w4 goto pc+0")
500*18b89265SEduard Zingerman __msg("frame 0: propagating r3,r4")
501*18b89265SEduard Zingerman __msg("11: safe")
502*18b89265SEduard Zingerman __msg("processed 15 insns")
__flag(BPF_F_TEST_STATE_FREQ)503*18b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
504*18b89265SEduard Zingerman __naked void no_scalar_id_for_const32(void)
505*18b89265SEduard Zingerman {
506*18b89265SEduard Zingerman 	asm volatile (
507*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
508*18b89265SEduard Zingerman 	/* unpredictable jump */
509*18b89265SEduard Zingerman 	"if r0 > 7 goto l0_%=;"
510*18b89265SEduard Zingerman 	/* possibly generate same scalar ids for r3 and r4 */
511*18b89265SEduard Zingerman 	"w1 = 0;"
512*18b89265SEduard Zingerman 	"w1 = w1;"
513*18b89265SEduard Zingerman 	"w3 = w1;"
514*18b89265SEduard Zingerman 	"w4 = w1;"
515*18b89265SEduard Zingerman 	"goto l1_%=;"
516*18b89265SEduard Zingerman "l0_%=:"
517*18b89265SEduard Zingerman 	/* possibly generate different scalar ids for r3 and r4 */
518*18b89265SEduard Zingerman 	"w1 = 0;"
519*18b89265SEduard Zingerman 	"w2 = 0;"
520*18b89265SEduard Zingerman 	"w3 = w1;"
521*18b89265SEduard Zingerman 	"w4 = w2;"
522*18b89265SEduard Zingerman "l1_%=:"
523*18b89265SEduard Zingerman 	/* predictable jump, marks r1 and r2 precise */
524*18b89265SEduard Zingerman 	"if w3 == w4 goto +0;"
525*18b89265SEduard Zingerman 	"r0 = 0;"
526*18b89265SEduard Zingerman 	"exit;"
527*18b89265SEduard Zingerman 	:
528*18b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
529*18b89265SEduard Zingerman 	: __clobber_all);
530*18b89265SEduard Zingerman }
531*18b89265SEduard Zingerman 
532*18b89265SEduard Zingerman /* Check that unique scalar IDs are ignored when new verifier state is
533*18b89265SEduard Zingerman  * compared to cached verifier state. For this test:
534*18b89265SEduard Zingerman  * - cached state has no id on r1
535*18b89265SEduard Zingerman  * - new state has a unique id on r1
536*18b89265SEduard Zingerman  */
537*18b89265SEduard Zingerman SEC("socket")
538*18b89265SEduard Zingerman __success __log_level(2)
539*18b89265SEduard Zingerman __msg("6: (25) if r6 > 0x7 goto pc+1")
540*18b89265SEduard Zingerman __msg("7: (57) r1 &= 255")
541*18b89265SEduard Zingerman __msg("8: (bf) r2 = r10")
542*18b89265SEduard Zingerman __msg("from 6 to 8: safe")
543*18b89265SEduard Zingerman __msg("processed 12 insns")
__flag(BPF_F_TEST_STATE_FREQ)544*18b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
545*18b89265SEduard Zingerman __naked void ignore_unique_scalar_ids_cur(void)
546*18b89265SEduard Zingerman {
547*18b89265SEduard Zingerman 	asm volatile (
548*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
549*18b89265SEduard Zingerman 	"r6 = r0;"
550*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
551*18b89265SEduard Zingerman 	"r0 &= 0xff;"
552*18b89265SEduard Zingerman 	/* r1.id == r0.id */
553*18b89265SEduard Zingerman 	"r1 = r0;"
554*18b89265SEduard Zingerman 	/* make r1.id unique */
555*18b89265SEduard Zingerman 	"r0 = 0;"
556*18b89265SEduard Zingerman 	"if r6 > 7 goto l0_%=;"
557*18b89265SEduard Zingerman 	/* clear r1 id, but keep the range compatible */
558*18b89265SEduard Zingerman 	"r1 &= 0xff;"
559*18b89265SEduard Zingerman "l0_%=:"
560*18b89265SEduard Zingerman 	/* get here in two states:
561*18b89265SEduard Zingerman 	 * - first: r1 has no id (cached state)
562*18b89265SEduard Zingerman 	 * - second: r1 has a unique id (should be considered equivalent)
563*18b89265SEduard Zingerman 	 */
564*18b89265SEduard Zingerman 	"r2 = r10;"
565*18b89265SEduard Zingerman 	"r2 += r1;"
566*18b89265SEduard Zingerman 	"exit;"
567*18b89265SEduard Zingerman 	:
568*18b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
569*18b89265SEduard Zingerman 	: __clobber_all);
570*18b89265SEduard Zingerman }
571*18b89265SEduard Zingerman 
572*18b89265SEduard Zingerman /* Check that unique scalar IDs are ignored when new verifier state is
573*18b89265SEduard Zingerman  * compared to cached verifier state. For this test:
574*18b89265SEduard Zingerman  * - cached state has a unique id on r1
575*18b89265SEduard Zingerman  * - new state has no id on r1
576*18b89265SEduard Zingerman  */
577*18b89265SEduard Zingerman SEC("socket")
578*18b89265SEduard Zingerman __success __log_level(2)
579*18b89265SEduard Zingerman __msg("6: (25) if r6 > 0x7 goto pc+1")
580*18b89265SEduard Zingerman __msg("7: (05) goto pc+1")
581*18b89265SEduard Zingerman __msg("9: (bf) r2 = r10")
582*18b89265SEduard Zingerman __msg("9: safe")
583*18b89265SEduard Zingerman __msg("processed 13 insns")
__flag(BPF_F_TEST_STATE_FREQ)584*18b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
585*18b89265SEduard Zingerman __naked void ignore_unique_scalar_ids_old(void)
586*18b89265SEduard Zingerman {
587*18b89265SEduard Zingerman 	asm volatile (
588*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
589*18b89265SEduard Zingerman 	"r6 = r0;"
590*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
591*18b89265SEduard Zingerman 	"r0 &= 0xff;"
592*18b89265SEduard Zingerman 	/* r1.id == r0.id */
593*18b89265SEduard Zingerman 	"r1 = r0;"
594*18b89265SEduard Zingerman 	/* make r1.id unique */
595*18b89265SEduard Zingerman 	"r0 = 0;"
596*18b89265SEduard Zingerman 	"if r6 > 7 goto l1_%=;"
597*18b89265SEduard Zingerman 	"goto l0_%=;"
598*18b89265SEduard Zingerman "l1_%=:"
599*18b89265SEduard Zingerman 	/* clear r1 id, but keep the range compatible */
600*18b89265SEduard Zingerman 	"r1 &= 0xff;"
601*18b89265SEduard Zingerman "l0_%=:"
602*18b89265SEduard Zingerman 	/* get here in two states:
603*18b89265SEduard Zingerman 	 * - first: r1 has a unique id (cached state)
604*18b89265SEduard Zingerman 	 * - second: r1 has no id (should be considered equivalent)
605*18b89265SEduard Zingerman 	 */
606*18b89265SEduard Zingerman 	"r2 = r10;"
607*18b89265SEduard Zingerman 	"r2 += r1;"
608*18b89265SEduard Zingerman 	"exit;"
609*18b89265SEduard Zingerman 	:
610*18b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
611*18b89265SEduard Zingerman 	: __clobber_all);
612*18b89265SEduard Zingerman }
613*18b89265SEduard Zingerman 
614*18b89265SEduard Zingerman /* Check that two different scalar IDs in a verified state can't be
615*18b89265SEduard Zingerman  * mapped to the same scalar ID in current state.
616*18b89265SEduard Zingerman  */
617*18b89265SEduard Zingerman SEC("socket")
618*18b89265SEduard Zingerman __success __log_level(2)
619*18b89265SEduard Zingerman /* The exit instruction should be reachable from two states,
620*18b89265SEduard Zingerman  * use two matches and "processed .. insns" to ensure this.
621*18b89265SEduard Zingerman  */
622*18b89265SEduard Zingerman __msg("13: (95) exit")
623*18b89265SEduard Zingerman __msg("13: (95) exit")
624*18b89265SEduard Zingerman __msg("processed 18 insns")
__flag(BPF_F_TEST_STATE_FREQ)625*18b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
626*18b89265SEduard Zingerman __naked void two_old_ids_one_cur_id(void)
627*18b89265SEduard Zingerman {
628*18b89265SEduard Zingerman 	asm volatile (
629*18b89265SEduard Zingerman 	/* Give unique scalar IDs to r{6,7} */
630*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
631*18b89265SEduard Zingerman 	"r0 &= 0xff;"
632*18b89265SEduard Zingerman 	"r6 = r0;"
633*18b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
634*18b89265SEduard Zingerman 	"r0 &= 0xff;"
635*18b89265SEduard Zingerman 	"r7 = r0;"
636*18b89265SEduard Zingerman 	"r0 = 0;"
637*18b89265SEduard Zingerman 	/* Maybe make r{6,7} IDs identical */
638*18b89265SEduard Zingerman 	"if r6 > r7 goto l0_%=;"
639*18b89265SEduard Zingerman 	"goto l1_%=;"
640*18b89265SEduard Zingerman "l0_%=:"
641*18b89265SEduard Zingerman 	"r6 = r7;"
642*18b89265SEduard Zingerman "l1_%=:"
643*18b89265SEduard Zingerman 	/* Mark r{6,7} precise.
644*18b89265SEduard Zingerman 	 * Get here in two states:
645*18b89265SEduard Zingerman 	 * - first:  r6{.id=A}, r7{.id=B} (cached state)
646*18b89265SEduard Zingerman 	 * - second: r6{.id=A}, r7{.id=A}
647*18b89265SEduard Zingerman 	 * Currently we don't want to consider such states equivalent.
648*18b89265SEduard Zingerman 	 * Thus "exit;" would be verified twice.
649*18b89265SEduard Zingerman 	 */
650*18b89265SEduard Zingerman 	"r2 = r10;"
651*18b89265SEduard Zingerman 	"r2 += r6;"
652*18b89265SEduard Zingerman 	"r2 += r7;"
653*18b89265SEduard Zingerman 	"exit;"
654*18b89265SEduard Zingerman 	:
655*18b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
656*18b89265SEduard Zingerman 	: __clobber_all);
657*18b89265SEduard Zingerman }
658*18b89265SEduard Zingerman 
659dec02028SEduard Zingerman char _license[] SEC("license") = "GPL";
660