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") 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") 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") 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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