233 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* 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 #1")36int 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 44SEC("iter/cgroup")45__description("uninitialized iter in ->destroy()")46__failure __msg("expected an initialized iter_bits as arg #1")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}233