On Thu, 2024-09-12 at 10:53 +0800, lonial con wrote: > I have never written a selftest before. I wrote a simple POC to > demonstrate this bug. This POC can crash the Linux kernel 6.6.50. I > think the ebpf code in the POC will be helpful for writing a > selftest. Well all depends on how familiar you want to get with selftests infrastructure :) Here is a promised intro. If you don't want to bother, please let me know, I can write the selftest. If you do want to bother, feel free to ask any questions. *** Please find a minimal recipe allowing to compile and run selftests in a chroot at the bottom of this email. You would probably want to adjust it, e.g. setup a user matching your local user inside chroot and do a bind mount for sources directory etc. After setting up the environment you will have to write the test. BPF selftests reside in the following directory: - tools/testing/selftests/bpf/ Nowadays we mostly add selftests to test_progs executable and use bpftool skeletons / libbpf to simplify maps and programs creation. The files located under prog_tests/ directory are compiled as host programs, the files located under progs/ are compiled as BPF programs (and libbpf skeletons are generated for these programs). Skeletons generated for files from progs/ are used in tests declared in prog_tests/. Your POC structure: - sets up a few maps - sets up data for ringbuf - loads and runs BPF program You can look at a selftests that have similar structure, e.g.: - tools/testing/selftests/bpf/prog_tests/ringbuf.c - tools/testing/selftests/bpf/progs/test_ringbuf.c Interesting parts of the 'prog_tests/ringbuf.c': // this includes skeleton generated by bpftool #include "test_ringbuf.lskel.h" static void ringbuf_subtest(void) { ... // use generated methods to setup maps and programs skel = test_ringbuf_lskel__open(); ... err = test_ringbuf_lskel__load(skel); // you can do bpf_prog_run here as well } // build system automatically wires up functions // void test_*(void) as entry points for tests // executed by test_progs binary void test_ringbuf(void) { // needed for tests filtering, e.g. -t option for test_progs if (test__start_subtest("ringbuf")) ringbuf_subtest(); ... } *** chroot selftests build/run recipe follows *** # First, setup the bullseye chroot sudo /usr/sbin/debootstrap --variant=buildd --arch=amd64 bullseye bullseye-chroot/ http://deb.debian.org/debian # provide {dev,proc} for chroot sudo mount --rbind /dev ./bullseye-chroot/dev/ sudo mount --make-rslave ./bullseye-chroot/dev/ sudo mount -t proc proc ./bullseye-chroot/proc/ # enter chroot sudo chroot ./bullseye-chroot # Install build tools apt install build-essential bc flex bison git libelf-dev libssl-dev \ docutils-common rsync curl zstd qemu-system-x86 sudo cmake \ libdw-dev lsb-release wget software-properties-common gnupg e2fsprogs # Install fresh clang-18 snapshot, the llvm.sh sets up some repos curl https://apt.llvm.org/llvm.sh --output /tmp/llvm.sh bash /tmp/llvm.sh 18 apt install clang-tools-18 ln -s /usr/bin/clang-18 /usr/bin/clang ln -s /usr/bin/llvm-strip-18 /usr/bin/llvm-strip # that would be /root inside chroot cd $HOME # Get and compile pahole, use instructions from: # https://git.kernel.org/pub/scm/devel/pahole/pahole.git/about/ git clone https://git.kernel.org/pub/scm/devel/pahole/pahole.git cd pahole git submodule update --init --recursive mkdir build cd build cmake -D__LIB=lib .. make -j # make it available system-wide ln -s $(realpath pahole) /usr/local/bin/ cd $HOME git clone --depth=1 https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git # Run vmtests, this should download rootfs, build kernel and tests, run test_verifier # vmtest.sh would ask for root password to mount rootfs image cd bpf-next/tools/testing/selftests/bpf ./vmtest.sh -- ./test_verifier # And now run test_progs ./vmtest.sh -- ./test_progs # One can filter tests too ./vmtest.sh -- ./test_progs -t ringbuf