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