Structure-Aware linux kernel Fuzzing with libFuzzer
Hi everyone! I’m really happy to tell you about my experimenting adventure today.
I decided to experiment with KCOV and see how I can hook it into libfuzzer and boot the kernel without spending too much on building a root file system.
First of all why not just using syzkaller? because why not? this may cover more State space.
after some googling I found a very interesting blog post by cloudflare
they have had answered my second question on how to boot newly built linux kernel with current root file system with
virtme
so basicall Virtme is a set of simple tools to run a virtualized Linux kernel that uses the host Linux distribution or a simple rootfs instead of a whole disk image.
Virtme is tiny, easy to use, and makes testing kernel changes quite simple.
I also borrowd some script from them.
So let’s get started:
clone virtme and linux kernel
you have to enable kcov for all targets with KCOV_INSTRUMENT_ALL or specific makefile.
Enable KCOV in all “fs” subdirectory:
then build linux kernel with KCOV and KASAN and some other flags needed by virtme
in order to provied kenrnel code coverage to libfuzzer we can use __libfuzzer_extra_counters, you can see a good example in syzkaller
and its documentation in kernel website
almost every kernel attack vector is Stateful APIs. you can’t just feed raw buffer to it. we have to use Structure-Aware Fuzzing, I deciede to use libprotobuf-mutator, which has show is very powerfull tool.
there are tons of resource out there about using libprotobuf-mutator.
I can’t explain better then original google fuzzing doc
Protocol Buffers As Intermediate Format
Protobufs provide a convenient way to serialize structured data, and LPM provides an easy way to mutate protobufs for structure-aware fuzzing. Thus, it is tempting to use libFuzzer+LPM for APIs that consume structured data other than protobufs.
but simply clone the repo and replace following code with this file
you can comment out other files in CMakeLists.txt because we want to modify .proto file.
for test you can use SockFuzzer to fuzz network stack.
The intriguing phase starts. If a kasan panics, libfuzzer lacks awareness and will dispose of the sample. Therefore, to preserve the triggering sample of the crash, we must inform libfuzzer about the kernel panic.
Initially, I explored alternative methods to notify the fuzzer about the panic. However, I opted to simulate SIGSEGV and dispatch a signal to libfuzzer whenever a kasan panic occurs in the kernel. Upon receiving this signal, libfuzzer will preserve the sample and terminate.
so we have to modify the linux kernel and build it once more.
add send_sigsegv_to_process function to print_error_description in /mm/kasan/report.c.
make sure
kernel.panic_on_warn=0
kernel.panic_on_oops=0
copy libprotobuf example binary to testfuzz. now you can boot the new kernel and run the fuzzer with
The next step involves incorporating APIs and system calls into the proto file and ensuring they are included in the DEFINE_PROTO_FUZZER. This will enable the ability to fuzz additional subsystems within the Linux kernel.