Loading...
Note: File does not exist in v6.8.
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
11char _license[] SEC("license") = "GPL";
12
13int bpf_iter_bits_new(struct bpf_iter_bits *it, const u64 *unsafe_ptr__ign,
14 u32 nr_bits) __ksym __weak;
15int *bpf_iter_bits_next(struct bpf_iter_bits *it) __ksym __weak;
16void bpf_iter_bits_destroy(struct bpf_iter_bits *it) __ksym __weak;
17
18u64 bits_array[511] = {};
19
20SEC("iter.s/cgroup")
21__description("bits iter without destroy")
22__failure __msg("Unreleased reference")
23int 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
33SEC("iter/cgroup")
34__description("uninitialized iter in ->next()")
35__failure __msg("expected an initialized iter_bits as arg #0")
36int BPF_PROG(next_uninit, struct bpf_iter_meta *meta, struct cgroup *cgrp)
37{
38 struct bpf_iter_bits it = {};
39
40 bpf_iter_bits_next(&it);
41 return 0;
42}
43
44SEC("iter/cgroup")
45__description("uninitialized iter in ->destroy()")
46__failure __msg("expected an initialized iter_bits as arg #0")
47int 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
55SEC("syscall")
56__description("null pointer")
57__success __retval(0)
58int 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
74SEC("syscall")
75__description("bits copy")
76__success __retval(10)
77int 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
88SEC("syscall")
89__description("bits memalloc")
90__success __retval(64)
91int 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
103SEC("syscall")
104__description("bit index")
105__success __retval(8)
106int 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
120SEC("syscall")
121__description("bits too big")
122__success __retval(0)
123int 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
135SEC("syscall")
136__description("fewer words")
137__success __retval(1)
138int 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
149SEC("syscall")
150__description("zero words")
151__success __retval(0)
152int 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
163SEC("syscall")
164__description("huge words")
165__success __retval(0)
166int 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
177SEC("syscall")
178__description("max words")
179__success __retval(4)
180int 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
198SEC("syscall")
199__description("bad words")
200__success __retval(0)
201int 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}