Syzkaller: Coverage-guided Kernel Fuzzer

2 minute read

Syzkaller is a coverage-guided fuzzer for Linux kernel, it was mainly developed by Dmitry Vyukov, and with many other developers, it’s under active development and have found many bugs and the latest reported bugs are listed on the dashboard of syzbot.

Syzkaller was first created for Linux kernels and now supporting many other OS kernels, but for this post, we’ll be only focusing on Android kernel fuzzing.

Build and Setup for Android

Syzkall was written in go, so first thing we need to do is get go compiler, I use below snippets to setup syzkaller environment on my ARM64 box.

machine=$(uname -m)

if [ "${machine}" = "aarch64" ]; then
    ARCH=arm64
elif [ "${machine}" = "x86_64" ]; then
    ARCH=amd64
fi

wget -c https://dl.google.com/go/go1.14.6.linux-${ARCH}.tar.gz
tar -xf go1.14.6.linux-${ARCH}.tar.gz
mv go $HOME/go/goroot
mkdir -p $HOME/go/gopath

cat << EOT >> .oh-my-zsh/custom/path.zsh
export GOPATH=$HOME/go/gopath
export GOROOT=$HOME/go/goroot
export PATH=$GOPATH/bin:$PATH
export PATH=$GOROOT/bin:$PATH
EOT

go get -u -d github.com/google/syzkaller/prog
cd $GOPATH/src/github.com/google/syzkaller/
make TARGETOS=linux TARGETARCH=arm64

I first build syzkaller on Ubuntu with Intel CPU without any problem, and later I switched an ARM64-based box as develop machine with 2GB RAM, which caused OOM when build syzkaller, you need to add a swap partition or swap file, 2GB will be OK for this.

Configuration for Android

In order to use syzkaller, we need to create a config file. syzkall use adb to communicate to the target board, if serial console is connected, it will associate adb with this serial console, you can find example config here, this is my config file based on that:

{
	"target": "linux/arm64",
	"http": "192.168.2.21:56789",
	"workdir": "/home/fdbai/go/gopath/src/github.com/google/syzkaller/workdir",
	"kernel_obj": "/opt/lineageos/kernel/kernel_rpi/",
	"syzkaller": "/home/fdbai/go/gopath/src/github.com/google/syzkaller",
	"sandbox": "none",
	"procs": 8,
	"type": "adb",
	"cover": true,
	"vm": {
		"devices": ["192.168.2.7:5555"],
		"timeout": 120,
		"battery_check": false
	}
}

For more config options refer to config.go.

Running syzkaller on Raspberry Pi will end up with adb push timeout, I created a patch adding timeout config option for these low-end embedded devices.

Kernel Configuration

As mentioned before, syzkaller is coverage-guided, therefor KCOV must be enabled, I made my list of configs based on this:

CONFIG_DEBUG_INFO=y
CONFIG_GDB_SCRIPTS=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_CRASH_DUMP=y
CONFIG_KEXEC=y
CONFIG_PROC_KCORE=y
CONFIG_KCOV=y
CONFIG_KCOV_ENABLE_COMPARISONS=y
CONFIG_KCOV_INSTRUMENT_ALL=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_MEMCG=y
CONFIG_CGROUP_PIDS=y
CONFIG_UBSAN=y
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_SECURITYFS=y
CONFIG_FAULT_INJECTION=y
CONFIG_FAILSLAB=y
CONFIG_FAIL_PAGE_ALLOC=y
CONFIG_FAIL_MAKE_REQUEST=y
CONFIG_FAIL_IO_TIMEOUT=y
CONFIG_FAIL_FUTEX=y
CONFIG_FAULT_INJECTION_DEBUG_FS=y

CONFIG_LOCKDEP=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_PROVE_RCU=y
CONFIG_DEBUG_VM=y
CONFIG_REFCOUNT_FULL=y
CONFIG_FORTIFY_SOURCE=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_WQ_WATCHDOG=y

CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=140
CONFIG_RCU_CPU_STALL_TIMEOUT=100

How to Use syzkaller

Now, we have everything needed, execute syz-manager with config file:

./bin/syz-manager -config=android.cfg

If there is something wrong with running above command, try to append -debug option to enable debug mode to see what’s happening there.

Web Interface

After the syzkall is up and running, you can view the realtime stats via it’s web interface which will be similar to this one: syzkall webui

Troubleshooting

make error

************************************************************************************
Executor will not be built
Native cross-compiler is missing/broken:
aarch64-linux-gnu-gcc: error trying to exec 'cc1plus': execvp: No such file or directory
************************************************************************************
sudo apt install gcc-8-aarch64-linux-gnu -y
sudo apt install g++-8-aarch64-linux-gnu -y

Failed to parse config file when running syz-manager

2020/07/24 10:01:46 failed to parse config file: invalid character ‘o’ in literal null (expecting ‘u’)

"sandbox": "none",

A: add double quote to none.

Failed to copy binary: timedout

2020/07/24 21:02:21 failed to copy binary: timedout ["adb" "-s" "192.168.1.7:5555" "push" "/home/fdbai/go/gopath/src/github.com/google/syzkaller/bin/linux_arm64/syz-fuzzer" "/data/syz-fuzzer"]

Kcsan does not exist

2019/08/03 09:23:32 concurrency sanitizer: /sys/kernel/debug/kcsan does not exist

Kernel Concurrency Sanitizer (KCSAN) was not supported by kernel v4.19.

References