Setup: Debian/Ubuntu host, QEMU vm, riscv64 kernel
GCC
Obtain riscv64-linux-gnu-gcc
at least GCC version 8. The latest Debian/Ubuntu distributions should
provide both cross-compilers in a recent enough version in the gcc-riscv64-linux-gnu
package.
Alternatively, you can also build your own
RISC-V GNU compiler toolchain from source.
Kernel
The following instructions were tested with Linux Kernel v5.9-rc1
. Create a kernel config with:
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
Also enable the recommended Kconfig options for syzkaller.
Then build kernel with:
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j $(nproc)
OpenSBI
Clone the OpenSBI repository and build the bootable OpenSBI image containg the kernel:
git clone https://github.com/riscv/opensbi
cd opensbi
make CROSS_COMPILE=riscv64-linux-gnu- PLATFORM_RISCV_XLEN=64 PLATFORM=generic
See the OpenSBI documentation for booting on the QEMU RISC-V Virt Machine Platform for more information.
Image
We will use buildroot to create the disk image. You can obtain buildroot here. The following instructions were tested with buildroot version 2020.05. First run:
make qemu_riscv64_virt_defconfig
make menuconfig
Choose the following options:
Target packages
Networking applications
[*] iproute2
[*] openssh
Filesystem images
ext2/3/4 variant - ext4
exact size - 1g
Unselect:
Kernel
Linux Kernel
Run make
.
Then add the following line to output/target/etc/fstab
:
debugfs /sys/kernel/debug debugfs defaults 0 0
Then replace output/target/etc/ssh/sshd_config
with the following contents:
PermitRootLogin yes
PasswordAuthentication yes
PermitEmptyPasswords yes
Run make
again.
QEMU
The following instructions were tested with QEMU 5.0. At least QEMU 4.1 is needed.
Test kernel and image
Run:
qemu-system-riscv64 \
-machine virt \
-nographic \
-bios /opensbi/build/platform/generic/firmware/fw_jump.bin \
-kernel /linux/arch/riscv/boot/Image \
-append "root=/dev/vda ro console=ttyS0" \
-object rng-random,filename=/dev/urandom,id=rng0 \
-device virtio-rng-device,rng=rng0 \
-drive file=/buildroot/output/images/rootfs.ext2,if=none,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0 \
-netdev user,id=net0,host=10.0.2.10,hostfwd=tcp::10022-:22 \
-device virtio-net-device,netdev=net0
This should boot the kernel. Wait for login prompt, then in another console run:
ssh -p 10022 root@localhost
ssh should succeed.
syzkaller
Build syzkaller as described here, with riscv64
target:
make TARGETOS=linux TARGETARCH=riscv64
Create the manager config riscv64.cfg
similar to the following one (adjusting paths as necessary):
{
"name": "riscv64",
"target": "linux/riscv64",
"http": ":56700",
"workdir": "/workdir",
"kernel_obj": "/linux",
"syzkaller": "/gopath/src/github.com/google/syzkaller",
"image": "/buildroot/output/images/rootfs.ext2",
"procs": 8,
"type": "qemu",
"vm": {
"count": 1,
"qemu_args": "-machine virt -bios /opensbi/build/platform/generic/firmware/fw_jump.bin",
"kernel": "/linux/arch/riscv/boot/Image",
"cpu": 2,
"mem": 2048
}
}
Alternatively, you may try to use the default OpenSBI firmware provided with QEMU 4.1 and newer by
specifying -machine virt -bios default
in qemu_args
and pass the kernel image in the kernel
config option:
{
"name": "riscv64",
"target": "linux/riscv64",
"http": ":56700",
"workdir": "/workdir",
"kernel_obj": "/linux",
"syzkaller": "/gopath/src/github.com/google/syzkaller",
"image": "/buildroot/output/images/rootfs.ext2",
"procs": 8,
"type": "qemu",
"vm": {
"count": 1,
"qemu_args": "-machine virt -bios default",
"kernel": "/linux/arch/riscv/boot/Image",
"cpu": 2,
"mem": 2048
}
}
This would allow to boot a different kernel without having to re-compile OpenSBI. However, on some
distributions the default OpenSBI firmware required by the -bios default
option might not be
available yet.
Finally, run bin/syz-manager -config riscv64.cfg
. After it successfully starts, you should be able
to visit localhost:56700
to view the fuzzing results.
In case you encounter issues with starting syz-manager
, use the -debug
flag and refer to the
troubleshooting guide.