初始环境配置
sudo apt-get install subversion
sudo apt-get install g++
sudo apt-get install git
sudo apt install libssl-dev libelf-dev
sudo apt-get install kvm qemu-kvm
安装 GCC
sudo apt-get install flex bison libc6-dev libc6-dev-i386 linux-libc-dev linux-libc-dev:i386 libgmp3-dev libmpfr-dev libmpc-dev
sudo apt-get install debootstrap
直接下载gcc环境
编译内核 启动
选择需要测试的内核版本,使用安装好的gcc进行编译
几种匹配,gcc8.0.1编译linux5.1.2编译比较流畅
make CC="/home/joeat1/gcc/bin/gcc" defconfig
make CC="/home/joeat1/gcc/bin/gcc" kvmconfig
以下内容需要写在中间位置,否则失效
CONFIG_KCOV=y
CONFIG_DEBUG_INFO=y
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y
需要开启内核上的CONFIG_KCOV选项,也可以在配置文件中加入”cover”: false即不需要使用覆盖率的信息进行测试
make CC="/home/joeat1/gcc/bin/gcc" oldconfig 运行此命令并在每次提示输入某个配置值时按Enter键将其保留为默认值
make CC="/home/joeat1/gcc/bin/gcc" -j64
//注意,此处不需要make install安装内核等组件
//注意,如果出现报错,可以不要 -j64 的选项
make clean CC="/home/joeat1/gcc/bin/gcc" CONFIG_KVM=m CONFIG_INTEL_KVM=m -C . M=./arch/x86/kvm
make CC="/home/joeat1/gcc/bin/gcc" CONFIG_KVM=m CONFIG_INTEL_KVM=m -C . M=./arch/x86/kvm
测试KVM虚拟机
qemu-system-x86_64
-kernel /home/joeat1/kernel/linux-5.1.2/arch/x86/boot/bzImage
-append "console=ttyS0 root=/dev/sda debug earlyprintk=serial slub_debug=QUZ"
-hda wheezy.img
-net user,hostfwd=tcp::10021-:22 -net nic
-enable-kvm
-nographic
-m 2G
-smp 2
-pidfile vm.pid
2>&1 | tee vm.log
-hda /home/joeat1/image/stretch.img
ssh -i /home/joeat1/image/stretch.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost
chmod 600 wheezy.img.key
ssh -i /home/joeat1/image/wheezy.img.key -p 10021 -o "StrictHostKeyChecking no" root@localhost
测试syz-manager
my.cfg
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "/home/joeat1/gopath/src/github.com/google/syzkaller/workdir",
"kernel_obj": "/home/joeat1/kernel/linux-5.1.2",
"image": "/home/joeat1/image/wheezy.img",
"sshkey": "/home/joeat1/image/wheezy.img.key",
"syzkaller": "/home/joeat1/gopath/src/github.com/google/syzkaller",
"procs": 8,
"type": "qemu",
"vm": {
"count": 4,
"kernel": "/home/joeat1/kernel/linux-5.1.2/arch/x86/boot/bzImage",
"cpu": 2,
"mem": 2048
},
"reproduce": false
}
mkdir workdir
./bin/syz-manager -config=my.cfg
ps -A | grep qemu
kill pid
kill $(cat vm.pid)
https://mirrors.kernel.org/debian/dists/wheezy/Release
SyscallName$Type (号前的syscallname是系统调用名,是内核提供的接口,在源码的)(SYZKALLER_SOURCE)/sys/sys.txt中有通用的调用的形式申明可以参考。$号后的type是指特定类型的系统调用。具体行为靠的是后面的参数去确定。
参数的格式如下: ArgumentName ArgumentType[Limit] ArgumentName是指参数名,ArgumentType指的是参数类型
"enable_syscalls": [
"socket(packet", "socketpair)packet", "accept(packet", "accept4)packet", "bind(packet", "connect)packet", "sendto(packet", "recvfrom)packet", "getsockname(packet", "getpeername)packet", "listen", "setsockopt", "getsockopt", "syz_emit_ethernet"
],
需要注意的是,此处写的方式,需要满足函数的参数对象能被创建,即关联关系保证连贯。
整个syzkaller的使用过程就是先去寻找内核的攻击面,然后构造api调用模板,剩下交由syzkaller基于代码覆盖驱动的方式去Fuzzing
"disable_syscalls": [
"socket$packet"
],
"enable_syscalls": [
"openat$kvm", "ioctl"
]
可能遇到的问题
sudo service sshd start
sudo service sshd status
use latest gcc and linux kernel will handle this problem
my configuration: gcc 8.4, linux-4.20.13
使用 -debug 显示所有的运行信息
[FAILED] Failed to mount /sys/kernel/config.
[FAILED] Failed to start Remount Root and Kernel File Systems.
The real cause of boot error is the missing of two config in kernel .config file:
CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y
https://github.com/google/syzkaller/blob/master/dashboard/config/upstream-kasan.config
使用syz-extract实用程序从内核源提取符号常量的值 。syz-extract生成一个小的C程序,包括include指令引用的内核头,定义define指令指定的宏,并打印符号常量的值。结果存储在.const文件中
使用syz-sysgen实用程序将描述转换为Go代码,此步骤使用系统调用描述和第一步中生成的const文件,并生成prog / types.go中定义的实例Syscall和Type类型。syzkaller使用由在prog / prog.go中定义的值Call和Arg值组成的内存中的AST表示
failed to generate coverage profile: '/home/joeat1/kernel/linux-5.1.2/vmlinux' does not have debug info (set CONFIG_DEBUG_INFO=y)
merged = bio_attempt_front_merge(q, rq, bio); 717
bio_attempt_front_merge 调用 ll_front_merge_fn 622
if (!ll_front_merge_fn(q, req, bio))
ll_front_merge_fn 在block/blk-merge.c:678 if (!bio_flagged(req->bio, BIO_SEG_VALID))处报错 kasan: GPF could be caused by NULL-ptr deref or user memory access
leak checking : CONFIG_DEBUG_KMEMLEAK is not enabled
使用syzkaller工具fuzz内核linux5.1.2模块,配置中设置enable_syscalls = ["openat(kvm","ioctl)KVM_CREATE_VM","ioctl(KVM_CREATE_VCPU","syz_kvm_setup_cpu)x86", "ioctl(KVM_SET_GUEST_DEBUG", "ioctl)KVM_RUN"],
得到可以crash信息,暂时未进行reproduce,和 https://syzkaller.appspot.com/bug?id=2bf7b7983c2398ec6f0c4c6c87cb50223e8873f8 中很相像
函数流程
kvm_cpu_vmxoff(void) --> cr4_clear_bits(X86_CR4_VMXE); --> __cr4_set(cr4 & ~mask); --> __write_cr4(cr4); --> PVOP_VCALL1(cpu.write_cr4, x);
不知道哪位大佬能帮忙解释解释?
Description Count Last Time Report
general protection fault in ll_front_merge_fn 2 2019/05/24 19:19
general protection fault in native_write_cr4 8 2019/05/24 19:28
KASAN: use-after-free Read in ll_back_merge_fn 3 2019/05/24 19:18
lost connection to test machine 16 2019/05/24 19:27
possible deadlock in __queue_work 1 2019/05/24 09:51
There are 3 special types of crashes:
- no output from test machine: the test machine produces no output whatsoever
- lost connection to test machine: the ssh connection to the machine was unexpectedly closed
- test machine is not executing programs: the machine looks alive, but no test programs were executed for long period of time
Most likely you won't see reportN files for these crashes (e.g. if there is no output from the test machine, there is nothing to put into report). Sometimes these crashes indicate a bug in syzkaller itself (especially if you see a Go panic message in the logs). However, frequently they mean a kernel lockup or something similarly bad (here are just a few examples of bugs found this way: 1, 2, 3).