Syzkaller Fuzz Android Kernel

Syzkaller官网上有关于如何对Android Kernel进行fuzz的方法,但是按照上面的步骤有很多不清楚的地方。
我的环境如下:
Android设备:Pixel
Android系统:Anroid9.0.0_r33

编译Android版Syzkaller

官网上是这么操作的:
以防你有旧的Android /dev/ion 驱动:

1
2
3
4
5
$ cp sys/android/* sys/linux
$ make generate
...
Makefile:196: recipe for target 'generate_sys' failed
make: *** [generate_sys] Error 1

会报错,现在还没找到解决方法。
编译arm64版syzkaller:

1
$ make TARGETOS=linux TARGETARCH=arm64

坑1:缺少交叉编译环境
aarch64-linux-gnu-gcc: Command not found
解决:

1
2
sudo apt install gcc-aarch64-linux-gnu
sudo apt install g++-aarch64-linux-gnu

编译Pixel Kernel with KASAN+KCOV

官网的操作方法:
首先需要下载编译AOSP,我下载编译的是Android9.0.0_r33,支持Pixel XL和Pixel。然后下载kernel:

1
2
3
$ git clone https://android.googlesource.com/kernel/msm
$ cd msm
$ git checkout TAG_NAME

官网上查到pixel(sailfish)对应的repo branch是android-msm-marlin-3.18-pie-qpr2,所以执行:

1
$ git checkout android-msm-marlin-3.18-pie-qpr2

执行完之后目录中就会有内容了。
编译过程如下:
1.设置交叉编译环境

1
2


按照官网介绍的方法对内核进行插桩之后,需要重新编译boot.img:

1
2
$ export TARGET_PREBUILT_KERNEL=/path/to/msm/arch/arm64/boot/Image.lz4-dtb
$ rm out/target/product/sailfish/boot.img && make bootimage

编译完的内核太大,make bootimage时会报错:

1
error:+out/target/product/sailfish/boot.img too large (*** > 335544432)

修改device/google/marlin/sailfish/BoardConfig.mk里的BOARD_BOOTIMAGE_PARTITION_SIZE。之后可以编译出boot.img,用如下命令刷入手机:

1
$ fastboot flash boot boot.img

但是刷到手机上时也会报boot.img太大的错误。在编译之前去掉.config文件里的SLUB_DEBUG选项,编译之后可以刷到手机上,但是手机会不断重启,目前还没有找到解决方法。
new
官网的KASAN+KCOV编译方法过时了,看官网编译Kernel的方法,新版内核都自带编译工具,使用./build/build.sh一键编译,查看根目录的build.config(symbolic link to private/msm-google/build.config):

1
2
3
4
5
KERNEL_DIR=private/msm-google
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
POST_DEFCONFIG_CMDS="check_defconfig && compression_tool_and_files lz4"
EXTRA_CMDS='python build/buildinfo/buildinfo.py'
STOP_SHIP_TRACEPRINTK=1

这个是Kernel的配置文件,包含了private/msm-google/build.config.common配置文件,并执行了check_defconfig和compression_tool_and_files两个函数,其中compress函数是build.config.common里定义的。
发现private/msm-google/目录下还有一个build.config.kasan配置文件,里面包含了build.config.common文件,还enable了Kernel的插桩选项,于是将根目录的build.config文件里的build.config.common替换为build.config.kasan:

1
2
3
4
5
6
KERNEL_DIR=private/msm-google
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.kasan
#. ${ROOT_DIR}/${KERNEL_DIR}/build.config.common
#POST_DEFCONFIG_CMDS="check_defconfig && compression_tool_and_files lz4"
#EXTRA_CMDS='python build/buildinfo/buildinfo.py'
STOP_SHIP_TRACEPRINTK=1

因为没有build/buildinfo/buildinfo.py文件,因此把它注释掉了。

运行Syzkaller

接下来就需要编写配置文件,运行Syzkaller了,配置文件adb.cfg如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"target": "linux/arm64",
"http": "localhost:50000",
"workdir": "/home/fanrong/gopath/src/github.com/google/syzkaller/androidir",
"syzkaller": "/home/fanrong/gopath/src/github.com/google/syzkaller",
"sandbox": "none",
"procs": 8,
"cover": false,
"type": "adb",
"vm": {
"devices": ["FA6880300195"],
"battery_check": false
}
}

“cover”: false是指测试目标是未插桩的。
其中的devices是usb连接手机后通过如下命令获取:

1
2
3
$ adb devices
List of devices attached
FA6880300195 device

之后常规启动syzkaller:

1
2
3
$ ./bin/syz-manager -config adb.cfg
...
failed to associate adb device FA6880300195 with console: no unassociated console devices left

会报一个没有console的错误,查看源码需要用到/dev/ttyUSB0的设备,然后我在/etc/udev/rules.d/51-android.rules里添加SYMLINK=”ttyUSB0”:

1
SUBSYSTEM=="usb",ATTRS{idVendor}=="18d1",ATTRS{idProduct}=="4ee7",MODE="0666",SYSLINK="ttyUSB0"

启动syzkaller:

1
2
3
$ ./bin/syz-manager -config adb.cfg
...
failed to associate adb device FA6880300195 with console: failed to get console termios: operation not permitted

目前关于console的这个错误还不知道怎么解决。