1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2024 Yafang Shao <laoar.shao@gmail.com> */
3
4 #include "vmlinux.h"
5 #include <bpf/bpf_helpers.h>
6 #include <bpf/bpf_tracing.h>
7
8 #include "bpf_misc.h"
9 #include "task_kfunc_common.h"
10
11 char _license[] SEC("license") = "GPL";
12
13 int bpf_iter_bits_new(struct bpf_iter_bits *it, const u64 *unsafe_ptr__ign,
14 u32 nr_bits) __ksym __weak;
15 int *bpf_iter_bits_next(struct bpf_iter_bits *it) __ksym __weak;
16 void bpf_iter_bits_destroy(struct bpf_iter_bits *it) __ksym __weak;
17
18 u64 bits_array[511] = {};
19
20 SEC("iter.s/cgroup")
21 __description("bits iter without destroy")
22 __failure __msg("Unreleased reference")
BPF_PROG(no_destroy,struct bpf_iter_meta * meta,struct cgroup * cgrp)23 int BPF_PROG(no_destroy, struct bpf_iter_meta *meta, struct cgroup *cgrp)
24 {
25 struct bpf_iter_bits it;
26 u64 data = 1;
27
28 bpf_iter_bits_new(&it, &data, 1);
29 bpf_iter_bits_next(&it);
30 return 0;
31 }
32
33 SEC("iter/cgroup")
34 __description("uninitialized iter in ->next()")
35 __failure __msg("expected an initialized iter_bits as arg #1")
BPF_PROG(next_uninit,struct bpf_iter_meta * meta,struct cgroup * cgrp)36 int BPF_PROG(next_uninit, struct bpf_iter_meta *meta, struct cgroup *cgrp)
37 {
38 struct bpf_iter_bits *it = NULL;
39
40 bpf_iter_bits_next(it);
41 return 0;
42 }
43
44 SEC("iter/cgroup")
45 __description("uninitialized iter in ->destroy()")
46 __failure __msg("expected an initialized iter_bits as arg #1")
BPF_PROG(destroy_uninit,struct bpf_iter_meta * meta,struct cgroup * cgrp)47 int BPF_PROG(destroy_uninit, struct bpf_iter_meta *meta, struct cgroup *cgrp)
48 {
49 struct bpf_iter_bits it = {};
50
51 bpf_iter_bits_destroy(&it);
52 return 0;
53 }
54
55 SEC("syscall")
56 __description("null pointer")
57 __success __retval(0)
null_pointer(void)58 int null_pointer(void)
59 {
60 struct bpf_iter_bits iter;
61 int err, nr = 0;
62 int *bit;
63
64 err = bpf_iter_bits_new(&iter, NULL, 1);
65 bpf_iter_bits_destroy(&iter);
66 if (err != -EINVAL)
67 return 1;
68
69 bpf_for_each(bits, bit, NULL, 1)
70 nr++;
71 return nr;
72 }
73
74 SEC("syscall")
75 __description("bits copy")
76 __success __retval(10)
bits_copy(void)77 int bits_copy(void)
78 {
79 u64 data = 0xf7310UL; /* 4 + 3 + 2 + 1 + 0*/
80 int nr = 0;
81 int *bit;
82
83 bpf_for_each(bits, bit, &data, 1)
84 nr++;
85 return nr;
86 }
87
88 SEC("syscall")
89 __description("bits memalloc")
90 __success __retval(64)
bits_memalloc(void)91 int bits_memalloc(void)
92 {
93 u64 data[2];
94 int nr = 0;
95 int *bit;
96
97 __builtin_memset(&data, 0xf0, sizeof(data)); /* 4 * 16 */
98 bpf_for_each(bits, bit, &data[0], ARRAY_SIZE(data))
99 nr++;
100 return nr;
101 }
102
103 SEC("syscall")
104 __description("bit index")
105 __success __retval(8)
bit_index(void)106 int bit_index(void)
107 {
108 u64 data = 0x100;
109 int bit_idx = 0;
110 int *bit;
111
112 bpf_for_each(bits, bit, &data, 1) {
113 if (*bit == 0)
114 continue;
115 bit_idx = *bit;
116 }
117 return bit_idx;
118 }
119
120 SEC("syscall")
121 __description("bits too big")
122 __success __retval(0)
bits_too_big(void)123 int bits_too_big(void)
124 {
125 u64 data[4];
126 int nr = 0;
127 int *bit;
128
129 __builtin_memset(&data, 0xff, sizeof(data));
130 bpf_for_each(bits, bit, &data[0], 512) /* Be greater than 511 */
131 nr++;
132 return nr;
133 }
134
135 SEC("syscall")
136 __description("fewer words")
137 __success __retval(1)
fewer_words(void)138 int fewer_words(void)
139 {
140 u64 data[2] = {0x1, 0xff};
141 int nr = 0;
142 int *bit;
143
144 bpf_for_each(bits, bit, &data[0], 1)
145 nr++;
146 return nr;
147 }
148
149 SEC("syscall")
150 __description("zero words")
151 __success __retval(0)
zero_words(void)152 int zero_words(void)
153 {
154 u64 data[2] = {0x1, 0xff};
155 int nr = 0;
156 int *bit;
157
158 bpf_for_each(bits, bit, &data[0], 0)
159 nr++;
160 return nr;
161 }
162
163 SEC("syscall")
164 __description("huge words")
165 __success __retval(0)
huge_words(void)166 int huge_words(void)
167 {
168 u64 data[8] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
169 int nr = 0;
170 int *bit;
171
172 bpf_for_each(bits, bit, &data[0], 67108865)
173 nr++;
174 return nr;
175 }
176
177 SEC("syscall")
178 __description("max words")
179 __success __retval(4)
max_words(void)180 int max_words(void)
181 {
182 volatile int nr = 0;
183 int *bit;
184
185 bits_array[0] = (1ULL << 63) | 1U;
186 bits_array[510] = (1ULL << 33) | (1ULL << 32);
187
188 bpf_for_each(bits, bit, bits_array, 511) {
189 if (nr == 0 && *bit != 0)
190 break;
191 if (nr == 2 && *bit != 32672)
192 break;
193 nr++;
194 }
195 return nr;
196 }
197
198 SEC("syscall")
199 __description("bad words")
200 __success __retval(0)
bad_words(void)201 int bad_words(void)
202 {
203 void *bad_addr = (void *)-4095;
204 struct bpf_iter_bits iter;
205 volatile int nr;
206 int *bit;
207 int err;
208
209 err = bpf_iter_bits_new(&iter, bad_addr, 1);
210 bpf_iter_bits_destroy(&iter);
211 if (err != -EFAULT)
212 return 1;
213
214 nr = 0;
215 bpf_for_each(bits, bit, bad_addr, 1)
216 nr++;
217 if (nr != 0)
218 return 2;
219
220 err = bpf_iter_bits_new(&iter, bad_addr, 4);
221 bpf_iter_bits_destroy(&iter);
222 if (err != -EFAULT)
223 return 3;
224
225 nr = 0;
226 bpf_for_each(bits, bit, bad_addr, 4)
227 nr++;
228 if (nr != 0)
229 return 4;
230
231 return 0;
232 }
233