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 
10 struct test_val {
11 	unsigned int index;
12 	int foo[MAX_ENTRIES];
13 };
14 
15 struct {
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 
22 SEC("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;				\
39 l0_%=:	exit;						\
40 "	:
41 	: __imm(bpf_map_lookup_elem),
42 	  __imm_addr(map_hash_48b)
43 	: __clobber_all);
44 }
45 
46 SEC("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;				\
63 l0_%=:	exit;						\
64 "	:
65 	: __imm(bpf_map_lookup_elem),
66 	  __imm_addr(map_hash_48b)
67 	: __clobber_all);
68 }
69 
70 SEC("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;				\
87 l0_%=:	exit;						\
88 "	:
89 	: __imm(bpf_map_lookup_elem),
90 	  __imm_addr(map_hash_48b)
91 	: __clobber_all);
92 }
93 
94 SEC("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;				\
112 l0_%=:	exit;						\
113 "	:
114 	: __imm(bpf_map_lookup_elem),
115 	  __imm_addr(map_hash_48b)
116 	: __clobber_all);
117 }
118 
119 SEC("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;				\
142 l0_%=:	exit;						\
143 "	:
144 	: __imm(bpf_map_lookup_elem),
145 	  __imm_addr(map_hash_48b)
146 	: __clobber_all);
147 }
148 
149 SEC("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 
168 char _license[] SEC("license") = "GPL";
169