1*caf345cfSEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2*caf345cfSEduard Zingerman /* Converted from tools/testing/selftests/bpf/verifier/map_ptr.c */
3*caf345cfSEduard Zingerman 
4*caf345cfSEduard Zingerman #include <linux/bpf.h>
5*caf345cfSEduard Zingerman #include <bpf/bpf_helpers.h>
6*caf345cfSEduard Zingerman #include "bpf_misc.h"
7*caf345cfSEduard Zingerman 
8*caf345cfSEduard Zingerman #define MAX_ENTRIES 11
9*caf345cfSEduard Zingerman 
10*caf345cfSEduard Zingerman struct test_val {
11*caf345cfSEduard Zingerman 	unsigned int index;
12*caf345cfSEduard Zingerman 	int foo[MAX_ENTRIES];
13*caf345cfSEduard Zingerman };
14*caf345cfSEduard Zingerman 
15*caf345cfSEduard Zingerman struct {
16*caf345cfSEduard Zingerman 	__uint(type, BPF_MAP_TYPE_ARRAY);
17*caf345cfSEduard Zingerman 	__uint(max_entries, 1);
18*caf345cfSEduard Zingerman 	__type(key, int);
19*caf345cfSEduard Zingerman 	__type(value, struct test_val);
20*caf345cfSEduard Zingerman } map_array_48b SEC(".maps");
21*caf345cfSEduard Zingerman 
22*caf345cfSEduard Zingerman struct other_val {
23*caf345cfSEduard Zingerman 	long long foo;
24*caf345cfSEduard Zingerman 	long long bar;
25*caf345cfSEduard Zingerman };
26*caf345cfSEduard Zingerman 
27*caf345cfSEduard Zingerman struct {
28*caf345cfSEduard Zingerman 	__uint(type, BPF_MAP_TYPE_HASH);
29*caf345cfSEduard Zingerman 	__uint(max_entries, 1);
30*caf345cfSEduard Zingerman 	__type(key, long long);
31*caf345cfSEduard Zingerman 	__type(value, struct other_val);
32*caf345cfSEduard Zingerman } map_hash_16b SEC(".maps");
33*caf345cfSEduard Zingerman 
34*caf345cfSEduard Zingerman SEC("socket")
35*caf345cfSEduard Zingerman __description("bpf_map_ptr: read with negative offset rejected")
36*caf345cfSEduard Zingerman __failure __msg("R1 is bpf_array invalid negative access: off=-8")
37*caf345cfSEduard Zingerman __failure_unpriv
38*caf345cfSEduard Zingerman __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
read_with_negative_offset_rejected(void)39*caf345cfSEduard Zingerman __naked void read_with_negative_offset_rejected(void)
40*caf345cfSEduard Zingerman {
41*caf345cfSEduard Zingerman 	asm volatile ("					\
42*caf345cfSEduard Zingerman 	r1 = r10;					\
43*caf345cfSEduard Zingerman 	r1 = %[map_array_48b] ll;			\
44*caf345cfSEduard Zingerman 	r6 = *(u64*)(r1 - 8);				\
45*caf345cfSEduard Zingerman 	r0 = 1;						\
46*caf345cfSEduard Zingerman 	exit;						\
47*caf345cfSEduard Zingerman "	:
48*caf345cfSEduard Zingerman 	: __imm_addr(map_array_48b)
49*caf345cfSEduard Zingerman 	: __clobber_all);
50*caf345cfSEduard Zingerman }
51*caf345cfSEduard Zingerman 
52*caf345cfSEduard Zingerman SEC("socket")
53*caf345cfSEduard Zingerman __description("bpf_map_ptr: write rejected")
54*caf345cfSEduard Zingerman __failure __msg("only read from bpf_array is supported")
55*caf345cfSEduard Zingerman __failure_unpriv
56*caf345cfSEduard Zingerman __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
bpf_map_ptr_write_rejected(void)57*caf345cfSEduard Zingerman __naked void bpf_map_ptr_write_rejected(void)
58*caf345cfSEduard Zingerman {
59*caf345cfSEduard Zingerman 	asm volatile ("					\
60*caf345cfSEduard Zingerman 	r0 = 0;						\
61*caf345cfSEduard Zingerman 	*(u64*)(r10 - 8) = r0;				\
62*caf345cfSEduard Zingerman 	r2 = r10;					\
63*caf345cfSEduard Zingerman 	r2 += -8;					\
64*caf345cfSEduard Zingerman 	r1 = %[map_array_48b] ll;			\
65*caf345cfSEduard Zingerman 	*(u64*)(r1 + 0) = r2;				\
66*caf345cfSEduard Zingerman 	r0 = 1;						\
67*caf345cfSEduard Zingerman 	exit;						\
68*caf345cfSEduard Zingerman "	:
69*caf345cfSEduard Zingerman 	: __imm_addr(map_array_48b)
70*caf345cfSEduard Zingerman 	: __clobber_all);
71*caf345cfSEduard Zingerman }
72*caf345cfSEduard Zingerman 
73*caf345cfSEduard Zingerman SEC("socket")
74*caf345cfSEduard Zingerman __description("bpf_map_ptr: read non-existent field rejected")
75*caf345cfSEduard Zingerman __failure
76*caf345cfSEduard Zingerman __msg("cannot access ptr member ops with moff 0 in struct bpf_map with off 1 size 4")
77*caf345cfSEduard Zingerman __failure_unpriv
78*caf345cfSEduard Zingerman __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
__flag(BPF_F_ANY_ALIGNMENT)79*caf345cfSEduard Zingerman __flag(BPF_F_ANY_ALIGNMENT)
80*caf345cfSEduard Zingerman __naked void read_non_existent_field_rejected(void)
81*caf345cfSEduard Zingerman {
82*caf345cfSEduard Zingerman 	asm volatile ("					\
83*caf345cfSEduard Zingerman 	r6 = 0;						\
84*caf345cfSEduard Zingerman 	r1 = %[map_array_48b] ll;			\
85*caf345cfSEduard Zingerman 	r6 = *(u32*)(r1 + 1);				\
86*caf345cfSEduard Zingerman 	r0 = 1;						\
87*caf345cfSEduard Zingerman 	exit;						\
88*caf345cfSEduard Zingerman "	:
89*caf345cfSEduard Zingerman 	: __imm_addr(map_array_48b)
90*caf345cfSEduard Zingerman 	: __clobber_all);
91*caf345cfSEduard Zingerman }
92*caf345cfSEduard Zingerman 
93*caf345cfSEduard Zingerman SEC("socket")
94*caf345cfSEduard Zingerman __description("bpf_map_ptr: read ops field accepted")
95*caf345cfSEduard Zingerman __success __failure_unpriv
96*caf345cfSEduard Zingerman __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
97*caf345cfSEduard Zingerman __retval(1)
ptr_read_ops_field_accepted(void)98*caf345cfSEduard Zingerman __naked void ptr_read_ops_field_accepted(void)
99*caf345cfSEduard Zingerman {
100*caf345cfSEduard Zingerman 	asm volatile ("					\
101*caf345cfSEduard Zingerman 	r6 = 0;						\
102*caf345cfSEduard Zingerman 	r1 = %[map_array_48b] ll;			\
103*caf345cfSEduard Zingerman 	r6 = *(u64*)(r1 + 0);				\
104*caf345cfSEduard Zingerman 	r0 = 1;						\
105*caf345cfSEduard Zingerman 	exit;						\
106*caf345cfSEduard Zingerman "	:
107*caf345cfSEduard Zingerman 	: __imm_addr(map_array_48b)
108*caf345cfSEduard Zingerman 	: __clobber_all);
109*caf345cfSEduard Zingerman }
110*caf345cfSEduard Zingerman 
111*caf345cfSEduard Zingerman SEC("socket")
112*caf345cfSEduard Zingerman __description("bpf_map_ptr: r = 0, map_ptr = map_ptr + r")
113*caf345cfSEduard Zingerman __success __failure_unpriv
114*caf345cfSEduard Zingerman __msg_unpriv("R1 has pointer with unsupported alu operation")
115*caf345cfSEduard Zingerman __retval(0)
map_ptr_map_ptr_r(void)116*caf345cfSEduard Zingerman __naked void map_ptr_map_ptr_r(void)
117*caf345cfSEduard Zingerman {
118*caf345cfSEduard Zingerman 	asm volatile ("					\
119*caf345cfSEduard Zingerman 	r0 = 0;						\
120*caf345cfSEduard Zingerman 	*(u64*)(r10 - 8) = r0;				\
121*caf345cfSEduard Zingerman 	r2 = r10;					\
122*caf345cfSEduard Zingerman 	r2 += -8;					\
123*caf345cfSEduard Zingerman 	r0 = 0;						\
124*caf345cfSEduard Zingerman 	r1 = %[map_hash_16b] ll;			\
125*caf345cfSEduard Zingerman 	r1 += r0;					\
126*caf345cfSEduard Zingerman 	call %[bpf_map_lookup_elem];			\
127*caf345cfSEduard Zingerman 	r0 = 0;						\
128*caf345cfSEduard Zingerman 	exit;						\
129*caf345cfSEduard Zingerman "	:
130*caf345cfSEduard Zingerman 	: __imm(bpf_map_lookup_elem),
131*caf345cfSEduard Zingerman 	  __imm_addr(map_hash_16b)
132*caf345cfSEduard Zingerman 	: __clobber_all);
133*caf345cfSEduard Zingerman }
134*caf345cfSEduard Zingerman 
135*caf345cfSEduard Zingerman SEC("socket")
136*caf345cfSEduard Zingerman __description("bpf_map_ptr: r = 0, r = r + map_ptr")
137*caf345cfSEduard Zingerman __success __failure_unpriv
138*caf345cfSEduard Zingerman __msg_unpriv("R0 has pointer with unsupported alu operation")
139*caf345cfSEduard Zingerman __retval(0)
_0_r_r_map_ptr(void)140*caf345cfSEduard Zingerman __naked void _0_r_r_map_ptr(void)
141*caf345cfSEduard Zingerman {
142*caf345cfSEduard Zingerman 	asm volatile ("					\
143*caf345cfSEduard Zingerman 	r0 = 0;						\
144*caf345cfSEduard Zingerman 	*(u64*)(r10 - 8) = r0;				\
145*caf345cfSEduard Zingerman 	r2 = r10;					\
146*caf345cfSEduard Zingerman 	r2 += -8;					\
147*caf345cfSEduard Zingerman 	r1 = 0;						\
148*caf345cfSEduard Zingerman 	r0 = %[map_hash_16b] ll;			\
149*caf345cfSEduard Zingerman 	r1 += r0;					\
150*caf345cfSEduard Zingerman 	call %[bpf_map_lookup_elem];			\
151*caf345cfSEduard Zingerman 	r0 = 0;						\
152*caf345cfSEduard Zingerman 	exit;						\
153*caf345cfSEduard Zingerman "	:
154*caf345cfSEduard Zingerman 	: __imm(bpf_map_lookup_elem),
155*caf345cfSEduard Zingerman 	  __imm_addr(map_hash_16b)
156*caf345cfSEduard Zingerman 	: __clobber_all);
157*caf345cfSEduard Zingerman }
158*caf345cfSEduard Zingerman 
159*caf345cfSEduard Zingerman char _license[] SEC("license") = "GPL";
160