Today, we are announcing Buzzer, a new eBPF Fuzzing framework that aims to help hardening the Linux Kernel.
What is eBPF and how does it verify safety?
eBPF is a technology that allows developers and sysadmins to easily run programs in a privileged context, like an operating system kernel. Recently, its popularity has increased, with more products adopting it as, for example, a network filtering solution. At the same time, it has maintained its relevance in the security research community, since it provides a powerful attack surface into the operating system.
While there are many solutions for fuzzing vulnerabilities in the Linux Kernel, they are not necessarily tailored to the unique features of eBPF. In particular, eBPF has many complex security rules that programs must follow to be considered valid and safe. These rules are enforced by a component of eBPF referred to as the "verifier". The correctness properties of the verifier implementation have proven difficult to understand by reading the source code alone.
That’s why our security team at Google decided to create a new fuzzer framework that aims to test the limits of the eBPF verifier through generating eBPF programs.
The eBPF verifier’s main goal is to make sure that a program satisfies a certain set of safety rules, for example: programs should not be able to write outside designated memory regions, certain arithmetic operations should be restricted on pointers, and so on. However, like all pieces of software, there can be holes in the logic of these checks. This could potentially cause unsafe behavior of an eBPF program and have security implications.
Introducing Buzzer a new way to fuzz eBPF
Buzzer aims to detect these errors in the verifier’s validation logic by generating a high volume of eBPF programs – around 35k per minute. It then takes each generated program and runs it through the verifier. If the verifier thinks it is safe, then the program is executed in a running kernel to determine if it is actually safe. Errors in the runtime behavior are detected through instrumentation code added by Buzzer.
It is with this technique that Buzzer found its first issue, CVE-2023-2163, an error in the branch pruning logic of the eBPF verifier that can cause unsafe paths to be overlooked, thus leading to arbitrary reading and writing of kernel memory. This issue demonstrates not only the complexity in the task that the verifier tries to accomplish (to make sure a program is safe in an efficient manner), but also how Buzzer can help researchers uncover complex bugs by automatically exploring corner cases in the verifier’s logic.
Additionally, Buzzer includes an easy to use eBPF generation library that makes it unique from other eBPF, or other general purpose Linux kernel fuzzers. By focusing on this particular technology, Buzzer is allowed to tailor its strategies to the eBPF features.
We are excited about the contributions Buzzer will make to the overall hardening of the Linux Kernel by making the eBPF implementation safer. Our team plans to develop some new features, such as the ability to run eBPF programs across distributed VMs.
Now that the code is open source, we are looking for contributors! If you have any interesting ideas for a feature we could implement in Buzzer, let us know in our GitHub repository.
We look forward to hearing your ideas and making eBPF safer together! Let the fuzzing begin.