1// SPDX-License-Identifier: GPL-2.0
2/* Converted from tools/testing/selftests/bpf/verifier/value_illegal_alu.c */
3
4#include <linux/bpf.h>
5#include <bpf/bpf_helpers.h>
6#include "bpf_misc.h"
7
8#define MAX_ENTRIES 11
9
10struct test_val {
11	unsigned int index;
12	int foo[MAX_ENTRIES];
13};
14
15struct {
16	__uint(type, BPF_MAP_TYPE_HASH);
17	__uint(max_entries, 1);
18	__type(key, long long);
19	__type(value, struct test_val);
20} map_hash_48b SEC(".maps");
21
22SEC("socket")
23__description("map element value illegal alu op, 1")
24__failure __msg("R0 bitwise operator &= on pointer")
25__failure_unpriv
26__naked void value_illegal_alu_op_1(void)
27{
28	asm volatile ("					\
29	r2 = r10;					\
30	r2 += -8;					\
31	r1 = 0;						\
32	*(u64*)(r2 + 0) = r1;				\
33	r1 = %[map_hash_48b] ll;			\
34	call %[bpf_map_lookup_elem];			\
35	if r0 == 0 goto l0_%=;				\
36	r0 &= 8;					\
37	r1 = 22;					\
38	*(u64*)(r0 + 0) = r1;				\
39l0_%=:	exit;						\
40"	:
41	: __imm(bpf_map_lookup_elem),
42	  __imm_addr(map_hash_48b)
43	: __clobber_all);
44}
45
46SEC("socket")
47__description("map element value illegal alu op, 2")
48__failure __msg("R0 32-bit pointer arithmetic prohibited")
49__failure_unpriv
50__naked void value_illegal_alu_op_2(void)
51{
52	asm volatile ("					\
53	r2 = r10;					\
54	r2 += -8;					\
55	r1 = 0;						\
56	*(u64*)(r2 + 0) = r1;				\
57	r1 = %[map_hash_48b] ll;			\
58	call %[bpf_map_lookup_elem];			\
59	if r0 == 0 goto l0_%=;				\
60	w0 += 0;					\
61	r1 = 22;					\
62	*(u64*)(r0 + 0) = r1;				\
63l0_%=:	exit;						\
64"	:
65	: __imm(bpf_map_lookup_elem),
66	  __imm_addr(map_hash_48b)
67	: __clobber_all);
68}
69
70SEC("socket")
71__description("map element value illegal alu op, 3")
72__failure __msg("R0 pointer arithmetic with /= operator")
73__failure_unpriv
74__naked void value_illegal_alu_op_3(void)
75{
76	asm volatile ("					\
77	r2 = r10;					\
78	r2 += -8;					\
79	r1 = 0;						\
80	*(u64*)(r2 + 0) = r1;				\
81	r1 = %[map_hash_48b] ll;			\
82	call %[bpf_map_lookup_elem];			\
83	if r0 == 0 goto l0_%=;				\
84	r0 /= 42;					\
85	r1 = 22;					\
86	*(u64*)(r0 + 0) = r1;				\
87l0_%=:	exit;						\
88"	:
89	: __imm(bpf_map_lookup_elem),
90	  __imm_addr(map_hash_48b)
91	: __clobber_all);
92}
93
94SEC("socket")
95__description("map element value illegal alu op, 4")
96__failure __msg("invalid mem access 'scalar'")
97__failure_unpriv __msg_unpriv("R0 pointer arithmetic prohibited")
98__flag(BPF_F_ANY_ALIGNMENT)
99__naked void value_illegal_alu_op_4(void)
100{
101	asm volatile ("					\
102	r2 = r10;					\
103	r2 += -8;					\
104	r1 = 0;						\
105	*(u64*)(r2 + 0) = r1;				\
106	r1 = %[map_hash_48b] ll;			\
107	call %[bpf_map_lookup_elem];			\
108	if r0 == 0 goto l0_%=;				\
109	r0 = be64 r0;					\
110	r1 = 22;					\
111	*(u64*)(r0 + 0) = r1;				\
112l0_%=:	exit;						\
113"	:
114	: __imm(bpf_map_lookup_elem),
115	  __imm_addr(map_hash_48b)
116	: __clobber_all);
117}
118
119SEC("socket")
120__description("map element value illegal alu op, 5")
121__failure __msg("R0 invalid mem access 'scalar'")
122__msg_unpriv("leaking pointer from stack off -8")
123__flag(BPF_F_ANY_ALIGNMENT)
124__naked void value_illegal_alu_op_5(void)
125{
126	asm volatile ("					\
127	r2 = r10;					\
128	r2 += -8;					\
129	r1 = 0;						\
130	*(u64*)(r2 + 0) = r1;				\
131	r1 = %[map_hash_48b] ll;			\
132	call %[bpf_map_lookup_elem];			\
133	if r0 == 0 goto l0_%=;				\
134	r3 = 4096;					\
135	r2 = r10;					\
136	r2 += -8;					\
137	*(u64*)(r2 + 0) = r0;				\
138	lock *(u64 *)(r2 + 0) += r3;			\
139	r0 = *(u64*)(r2 + 0);				\
140	r1 = 22;					\
141	*(u64*)(r0 + 0) = r1;				\
142l0_%=:	exit;						\
143"	:
144	: __imm(bpf_map_lookup_elem),
145	  __imm_addr(map_hash_48b)
146	: __clobber_all);
147}
148
149SEC("flow_dissector")
150__description("flow_keys illegal alu op with variable offset")
151__failure __msg("R7 pointer arithmetic on flow_keys prohibited")
152__naked void flow_keys_illegal_variable_offset_alu(void)
153{
154	asm volatile("					\
155	r6 = r1;					\
156	r7 = *(u64*)(r6 + %[flow_keys_off]);		\
157	r8 = 8;						\
158	r8 /= 1;					\
159	r8 &= 8;					\
160	r7 += r8;					\
161	r0 = *(u64*)(r7 + 0);				\
162	exit;						\
163"	:
164	: __imm_const(flow_keys_off, offsetof(struct __sk_buff, flow_keys))
165	: __clobber_all);
166}
167
168char _license[] SEC("license") = "GPL";
169