GSoC'21 Final Report
Project: Syzkaller improvements
Student: Simran Kathpalia
Goal: To enhance the existing state of syzkaller support in FreeBSD.
To achieve this, the project was divided into subtasks:-
- Adding syscalls and device drivers to syzkaller.
- Automating the generation of syscalls and ioctl calls.
- Fuzzing FreeBSD’s Linux compatibility layer.
- Improving fuzzing for subsystems(USB traffic).
- Patching syzkaller reported bugs.
- I looked into the syscall support of NetBSD and extracted the syscalls which were missing from FreeBSD. These could be easily added to FreeBSD with slight tweaking.
Next, I looked into coverage of FreeBSD syscalls and got a list of missing syscalls.
- Some of the major groups of syscalls added to syzkaller are:
I could increase the syscall coverage of syscalls added under FreeBSD to syzkaller by 9 percent.
Added a bunch of device drivers:-
- Checked each man page and corresponding header and C files in FreeBSD source, to get all the ioctl calls for a selected device driver. Next, I got the associated structures, unions, and flags to the ioctl call. Followed the documentation which describes rules for writing syscall descriptions. Compiled all the ioctl calls for the device driver into a file.
- The ioctl calls added:
bpf(4) along with necessary path change.
An existing tool(sys2syz) which is used to extract descriptions for NetBSD, was modified to also support FreeBSD. It extracts the ioctl calls and their arguments from header files, compiles the kernel to get the type and macros, and then converts into the format supported by syzkaller. The tool will soon be integrated with the original repository.
- The ioctls tested in FreeBSD and then added to syzkaller:
Linuxulator fuzzing is basically fuzzing the linux binary compatibility layer (mechanism to run unmodified Linux binaries under FreeBSD). It is similar to how 32 bit FreeBSD binaries run on 64 bit FreeBSD kernel. Currently, in syzkaller, there are three tuples that define the whole target OS. These are TARGETOS, TARGETARCH, TARGETVMARCH. To fuzz the 32 bit compatibility layer, we pass arguments as TARGETOS=FreeBSD, TARGETARCH=i386, and TARGETVMARCH=amd64.
To fuzz the Linux compatibility layer, the idea is to add a 4th tuple to define the target which now makes the whole target OS as TARGETOS, TARGETVMOS, TARGETARCH, TARGETVMARCH. Using this we can fuzz 64 bit Linux layer (linux, freebsd, amd64, amd64) or even 32 bit Linux layer (linux, freebsd, i386, amd64).
With the help of my mentor, I split up the original TARGETOS into TARGETOS or TARGETVMOS, making it target the right kernel interface. The syz-manager fuzzes the FreeBSD itself but it has to target the Linux layer inside. I inspected quite a few occurrences of TARGETOS and subsequently made changes. There is still some amount of testing to be done but is near completion.
Here is the updated work: Latest fork
There are quite a few bugs reported by syzkaller as a result of adding the description for syscalls and device drivers. Some are already patched some are yet to be patched.
From aio(4):- https://syzkaller.appspot.com/bug?id=014369febb828b519ce5094bcec5a2c46bd991ad
From md(4):- https://syzkaller.appspot.com/bug?id=287c28a7c9cc6a0be01eed27d6e61c14a5d305ad
Patching of kernel bugs
I worked on two kernel bugs reported by syzkaller which were found with KMSAN (Kernel Memory SANitizer) enabled. They were both based on the usage of uninitialized memory. I could build the kernel with KMSAN enabled and reproduce the bug. With the help of kgdb and basic debugging, I could detect the point of the trigger of the panic. I was able to patch one of the bugs and had a basic understanding of the other one. One was located in the crypto device driver which was triggering a panic because of an uninitialized value being passed to another variable. This was due to a missing check for MAC (digest) in case mac was not provided by userspace. Here’s the patch I added. The other was located in get_socketop() where one of the socket options was not initialized properly and thus triggering a panic. This was found and patched by another developer.
The main objective of the project was to increase FreeBSD’s coverage and all the work has been done in this direction. However, there is still a task left which is one of many ways to increase the coverage. One of the tasks was to look into external USB fuzzing which has not been addressed yet. But I plan to look into it.
GSoC was a tremendous learning experience for me, wherein I worked on a fuzzer and understood the logic behind it. I dealt with a lot of syscalls and device drivers and their applications and working. I also got to learn about kernel bugs and how to debug them. Overall, it was an immensely steep learning curve, concentrated in the last few months.
I plan on staying in touch with my mentors and finishing up the rest of the project. And if possible, work on patching more kernel related bugs. My mentor has been very helpful and supportive, which makes me more excited about working with him in the future.