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 int nr = 0; 61 int *bit; 62 63 bpf_for_each(bits, bit, NULL, 1) 64 nr++; 65 return nr; 66 } 67 68 SEC("syscall") 69 __description("bits copy") 70 __success __retval(10) 71 int bits_copy(void) 72 { 73 u64 data = 0xf7310UL; /* 4 + 3 + 2 + 1 + 0*/ 74 int nr = 0; 75 int *bit; 76 77 bpf_for_each(bits, bit, &data, 1) 78 nr++; 79 return nr; 80 } 81 82 SEC("syscall") 83 __description("bits memalloc") 84 __success __retval(64) 85 int bits_memalloc(void) 86 { 87 u64 data[2]; 88 int nr = 0; 89 int *bit; 90 91 __builtin_memset(&data, 0xf0, sizeof(data)); /* 4 * 16 */ 92 bpf_for_each(bits, bit, &data[0], ARRAY_SIZE(data)) 93 nr++; 94 return nr; 95 } 96 97 SEC("syscall") 98 __description("bit index") 99 __success __retval(8) 100 int bit_index(void) 101 { 102 u64 data = 0x100; 103 int bit_idx = 0; 104 int *bit; 105 106 bpf_for_each(bits, bit, &data, 1) { 107 if (*bit == 0) 108 continue; 109 bit_idx = *bit; 110 } 111 return bit_idx; 112 } 113 114 SEC("syscall") 115 __description("bits too big") 116 __success __retval(0) 117 int bits_too_big(void) 118 { 119 u64 data[4]; 120 int nr = 0; 121 int *bit; 122 123 __builtin_memset(&data, 0xff, sizeof(data)); 124 bpf_for_each(bits, bit, &data[0], 512) /* Be greater than 511 */ 125 nr++; 126 return nr; 127 } 128 129 SEC("syscall") 130 __description("fewer words") 131 __success __retval(1) 132 int fewer_words(void) 133 { 134 u64 data[2] = {0x1, 0xff}; 135 int nr = 0; 136 int *bit; 137 138 bpf_for_each(bits, bit, &data[0], 1) 139 nr++; 140 return nr; 141 } 142 143 SEC("syscall") 144 __description("zero words") 145 __success __retval(0) 146 int zero_words(void) 147 { 148 u64 data[2] = {0x1, 0xff}; 149 int nr = 0; 150 int *bit; 151 152 bpf_for_each(bits, bit, &data[0], 0) 153 nr++; 154 return nr; 155 } 156 157 SEC("syscall") 158 __description("huge words") 159 __success __retval(0) 160 int huge_words(void) 161 { 162 u64 data[8] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; 163 int nr = 0; 164 int *bit; 165 166 bpf_for_each(bits, bit, &data[0], 67108865) 167 nr++; 168 return nr; 169 } 170 171 SEC("syscall") 172 __description("max words") 173 __success __retval(4) 174 int max_words(void) 175 { 176 volatile int nr = 0; 177 int *bit; 178 179 bits_array[0] = (1ULL << 63) | 1U; 180 bits_array[510] = (1ULL << 33) | (1ULL << 32); 181 182 bpf_for_each(bits, bit, bits_array, 511) { 183 if (nr == 0 && *bit != 0) 184 break; 185 if (nr == 2 && *bit != 32672) 186 break; 187 nr++; 188 } 189 return nr; 190 } 191 192 SEC("syscall") 193 __description("bad words") 194 __success __retval(0) 195 int bad_words(void) 196 { 197 void *bad_addr = (void *)(3UL << 30); 198 int nr = 0; 199 int *bit; 200 201 bpf_for_each(bits, bit, bad_addr, 1) 202 nr++; 203 204 bpf_for_each(bits, bit, bad_addr, 4) 205 nr++; 206 207 return nr; 208 } 209