Author: geneblue
Blog: https://geneblue.github.io/
安装
使用 syzkaller fuzz linux kernel,需要安装以下工具。
- 支持 coverage 的 C 编译器
- 支持 coverage 配置的 linux 内核
- QEME 和 磁盘镜像或者真机
- syzkaller
C 编译器
syzkaller 是个基于代码覆盖率的 fuzz工具,这要求内核需要支持代码覆盖,这就需要一个 支持代码覆盖的编译器来编译内核。gcc6 版本 231296 开始增加了对代码覆盖的支持,所以 我们可以使用 gcc6 来编译内核。
下载编译 gcc6: 1
2
3
4
5
6
7
8
9
10
11svn checkout svn://gcc.gnu.org/svn/gcc/trunk gcc_src
cd gcc_src
svn ls -v ^/tags | grep gcc_8_2_0_release
svn up -r 262993
mkdir build
mkdir install
cd build/
sudo apt-get install flex bison libc6-dev libc6-dev-i386 linux-libc-dev linux-libc-dev:i386 libgmp3-dev libmpfr-dev libmpc-dev
../configure --enable-languages=c,c++ --disable-bootstrap --enable-checking=no --with-gnu-as --with-gnu-ld --with-ld=/usr/bin/ld.bfd --disable-multilib --prefix=gcc_src/install/
make -j16
make install
Linux 内核 和 gcc6 一样,内核本身也要增加对代码覆盖的支持。
- build 内核时增加对代码覆盖的支持(CONFIG_KCOV)
- 在系统调用 entry/exit 中增加额外的指令
- 添加代码来跟踪报告每个任务的代码覆盖信息
KCOV 配置已经添加到了上游代码 linux4.6 中,对于较老的内核需要移植 commit 5c9a8750a6409c63a0f01d51a9024861022f6593,该commit 基本上就是在内核中添加对 KCOV 特性的支持。编译内核时推荐使用如下配置:
对代码覆盖的支持: 1
2
3
4CONFIG_KCOV=y
CONFIG_KCOV_INSTRUMENT_ALL=y
CONFIG_KCOV_ENABLE_COMPARISONS=y
CONFIG_DEBUG_FS=y
在 web 接口显示代码覆盖: 1
CONFIG_DEBUG_INFO=y
内核符号信息: 1
2CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
namespace 沙箱: 1
2
3
4
5
6
7
8CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_CGROUP_PIDS=y
CONFIG_MEMCG=y
CONFIG_USER_NS=y
如果 kernel 运行在 VMs 中,在编译内核时可以使用 make
kvmconfig
使用 Debian 文件镜像(由tools/create-image.sh生成)还需要:
1
2CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y
开启 KASAN 支持对 use-after-free 和 out-of-bounds 的检测:
1
2CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y
打开其他调试选项对 fuzz 的支持更好,如下是比较推荐的:
1
2
3
4
5CONFIG_LOCKDEP=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_PROVE_RCU=y
CONFIG_DEBUG_VM=y
关闭下述配置: 1
# CONFIG_RANDOMIZE_BASE is not set
增加 RCU 时延: 1
CONFIG_RCU_CPU_STALL_TIMEOUT=60
编译 linux 内核: 1
2
3
4
5
6
7
8
9
10git clone https://github.com/torvalds/linux.git $KERNEL
cd $KERNEL
make defconfig
make kvmconfig
# Edit .config to set CONFIG_KCOV=y
# Edit .config to set CONFIG_DEBUG_INFO=y
# Edit .config to set CONFIG_KASAN=y
make oldconfig
# Select KASAN_INLINE when prompted, leave other options default
make CC='$GCC/install/bin/gcc' -j64
QEMU 配置 syzkaller 在 QEMU 虚拟机中运行 fuzz 进程,所以这里还需要配置 QEMU,QEMU 的安装可以参考 QEMU 官网.
但以下几点需要注意: - fuzzing 进程需要和外面世界通信,所以 VM
镜像需要包含对 networking 的支持 - fuzzer 进程的程序文件需要通过 SSH
传入到 VM 中,所以 VM 镜像需要运行 SSH server - VM 的 SSH
配置应该被设置成允许 syz-manager 配置的 root 权限访问。还句话说,在执行
ssh -i $SSHID -p $PORT root@localhost
时没有任何提示,也不要求输入密码(SSHID 是 SSH 的凭证,PORT 表示
syz-manager 配置文件中指定的端口号) - 内核通过 debugfs 入口来导出
代码覆盖信息,所以 VM 镜像 需要 在 /sys/kernel/debug
处
mount debugfs 文件系统
create-image.sh 脚本用于创建一个 linux 镜像。
Syzkaller 也支持 kvmtools VMs,GCE VMs 或运行在真实的 Android 设备中。
Syzkaller syzkaller 是 go 语言编写而成,所以需要 go 编译器(>=1.9)来编译 syzkaller。
到https://golang.org/dl/站点下载
go
包,将其解压到目录$HOME/go
中,然后添加环境变量GOROOT=$HOME/go
,PATH=$HOME/go/bin:$PATH
,GOPATH=$HOME/gopath
,运行命令go
get -d github.com/google/syzkaller/...
checkout 出 syzkaller
源码及其依赖,进入到
$GOPATH/src/github.com/google/syzkaller
目录,运行命令
make
即可将 syzkaller 编译到 bin\
目录下。
go 的站点被墙了,导致有些包下载不下来,可以到第三方站点上下载离线包,再手动解包。
1 | wget https://dl.google.com/go/go1.10.linux-amd64.tar.gz |
配置 go 环境变量 1
2
3GOROOT=$HOME/go
PATH=$HOME/go/bin:$PATH
GOPATH=$HOME/gopath
使用 go 下载编译 syzkaller 1
2
3go get -d github.com/google/syzkaller/...
cd $GOPATH/src/github.com/google/syzkaller
make