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