BRF is a coverage-guided fuzzer that aims to fuzz the runtime compononets of eBPF shielded by the verifier. BRF uses semantic-aware and dependency-aware input generation/mutation logic as well as generating syscalls to trigger the execution of eBPF programs to achieve the goal. The implementation of BRF is based on Syzkaller.
To use latest bpf features, it is better to build the kernel using the latest llvm.
git clone --branch llvmorg-17.0.6 https://github.com/llvm/llvm-project.git
mkdir llvm-project/build; cd llvm-project/build
cmake ../llvm -DLLVM_TARGETS_TO_BUILD="BPF;X86" \
-DLLVM_ENABLE_PROJECTS=clang \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_BUILD_RUNTIME=OFF
make
After the build completes, export build/bin to $PATH.
git clone --branch v1.24 https://github.com/acmel/dwarves.git
mkdir dwarves/build; cd dwarves/build
cmake ../
make
sudo make install
More to be added. Let us know if you think something should be added here.
Here we use the development branch of network device subsystem of the Linux kernel.
git clone https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git $KERNEL
cd $KERNEL
make CC=clang-17 defconfig
make CC=clang-17 kvm_guest.config
Follow the guide and enable kernel configs required by Syzkaller
Enable bpf-related configs by editing .config or through menuconfig.
CONFIG_BPF_SYSCALL
CONFIG_BPF_JIT
CONFIG_BPF_LSM
CONFIG_DEBUG_INFO_BTF
CONFIG_MODULE_ALLOW_BTF_MISMATCH
CONFIG_TEST_BPF
CONFIG_CGROUP_BPF
CONFIG_NET_ACT_BPF
CONFIG_NET_CLS_BPF
CONFIG_BPF_STREAM_PARSER
CONFIG_LWTUNNEL_BPF
CONFIG_IPV6_SEG6_BPF
CONFIG_LIRC
CONFIG_BPF_LIRC_MODE2
Finally, build the Linux kernel with Clang/LLVM.
make CC=clang-17
Build bpftool and libbpf to be used later
cd $KERNEL/tools/bpf/bpftool
make CC=clang-17
cd $KERNEL/tools/lib/bpf
make
mkdir $IMAGE; cd $IMAGE
cp $SYZKALLER/tools/create-image.sh .
chmod +x create-image.sh
ADD_PACKAGE="make,sysbench,git,vim,tmux,usbutils,tcpdump,clang-16" ./create-image.sh --feature full --distribution bookworm --seek 8191
Prepare BRF working directory. The directory will be shared with the guest to store and compile BPF programs.
mkdir $BRF_WORKDIR; cd $BRF_WORKDIR
cp $KERNEL/tools/bpf/bpftool/vmlinux.h .
Boot into the guest and install libbpf headers.
qemu-system-x86_64 \
-m 2G \
-smp 2 \
-kernel $KERNEL/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
-drive file=$IMAGE/bookworm.img,format=raw \
-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
-net nic,model=e1000 \
-virtfs local,path=$KERNEL,mount_tag=host0,security_model=mapped,id=host0 \
-enable-kvm \
-nographic \
-pidfile vm.pid \
2>&1 | tee vm.log
mkdir /mnt/kernel_src
mount -t 9p -o trans=virtio,version=9p2000.L host0 /mnt/kernel_src
cd /mnt/kernel_src/tools/lib/bpf
make install_headers
Create a config like the following and replace $SYZKALLER, $KERNEL, $IMAGE and $BRF_WORKDIR with the actual paths.
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "$SYZKALLER/workdir/bookworm",
"kernel_obj": "$KERNEL",
"image": "$IMAGE/bookworm.img",
"sshkey": "$IMAGE/bookworm.id_rsa",
"syzkaller": "$SYZKALLER",
"procs": 8,
"type": "qemu",
"vm": {
"count": 4,
"kernel": "$KERNEL/arch/x86/boot/bzImage",
"cpu": 2,
"mem": 2048,
"brf_workdir": "$BRF_WORKDIR"
}
}
Run Syzkaller manager:
mkdir -p workdir/bookworm
./bin/syzkaller -config my.cfg
The work was supported in part by NSF Awards #1763172 and #1846230 as well as Google’s 2020 Android Security and PrIvacy REsearch (ASPIRE) Award.