• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Setup: Ubuntu host, QEMU vm, x86-64 kernel
2
3These are the instructions on how to fuzz the x86-64 kernel in a QEMU with Ubuntu 14.04 on the host machine and Debian Wheezy in the QEMU instances.
4
5## GCC
6
7Since syzkaller requires coverage support in GCC, we need to use a recent GCC version. To checkout GCC 7.1.0 sources to `$GCC` dir:
8``` bash
9svn checkout svn://gcc.gnu.org/svn/gcc/trunk $GCC
10cd $GCC
11svn ls -v ^/tags | grep gcc_7_1_0_release
12svn up -r 247494
13```
14
15Unfortunately there's a typo in the source of `gcc_7_1_0_release`. Apply [this fix](https://patchwork.ozlabs.org/patch/757421/):
16``` c
17diff --git a/gcc/tree.h b/gcc/tree.h
18index 3bca90a..fdaa7af 100644
19--- a/gcc/tree.h
20+++ b/gcc/tree.h
21@@ -897,8 +897,8 @@  extern void omp_clause_range_check_failed (const_tree, const char *, int,
22 /* If this is true, we should insert a __cilk_detach call just before
23    this function call.  */
24 #define EXPR_CILK_SPAWN(NODE) \
25-  (tree_check2 (NODE, __FILE__, __LINE__, __FUNCTION__, \
26-                CALL_EXPR, AGGR_INIT_EXPR)->base.u.bits.unsigned_flag)
27+  (TREE_CHECK2 (NODE, CALL_EXPR, \
28+                AGGR_INIT_EXPR)->base.u.bits.unsigned_flag)
29
30 /* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is
31    passed by invisible reference (and the TREE_TYPE is a pointer to the true
32```
33
34Install GCC prerequisites:
35```
36sudo apt-get install flex bison libc6-dev libc6-dev-i386 linux-libc-dev linux-libc-dev:i386 libgmp3-dev libmpfr-dev libmpc-dev build-essential bc
37```
38
39Build GCC:
40``` bash
41mkdir build
42mkdir install
43cd build/
44../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/install/
45make -j64
46make install
47```
48
49Now you should have GCC binaries in `$GCC/install/bin/`:
50``` bash
51$ ls $GCC/install/bin/
52c++  gcc-ar      gcov-tool                x86_64-pc-linux-gnu-gcc-7.0.0
53cpp  gcc-nm      x86_64-pc-linux-gnu-c++  x86_64-pc-linux-gnu-gcc-ar
54g++  gcc-ranlib  x86_64-pc-linux-gnu-g++  x86_64-pc-linux-gnu-gcc-nm
55gcc  gcov        x86_64-pc-linux-gnu-gcc  x86_64-pc-linux-gnu-gcc-ranlib
56```
57
58## Kernel
59
60Checkout Linux kernel source:
61``` bash
62git clone https://github.com/torvalds/linux.git $KERNEL
63```
64
65Generate default configs:
66``` bash
67cd $KERNEL
68make defconfig
69make kvmconfig
70```
71
72Now we need to enable some config options required for syzkaller.
73Edit `.config` file manually and enable:
74```
75CONFIG_KCOV=y
76CONFIG_DEBUG_INFO=y
77CONFIG_KASAN=y
78CONFIG_KASAN_INLINE=y
79```
80
81You might also want to enable some other kernel configs as described [here](kernel_configs.md).
82
83Since enabling these options results in more sub options being available, we need to regenerate config. Run this and press enter each time when prompted for some config value to leave it as default:
84``` bash
85make oldconfig
86```
87
88Build the kernel with previously built GCC:
89```
90make CC="$GCC/install/bin/gcc" -j64
91```
92
93Now you should have `vmlinux` (kernel binary) and `bzImage` (packed kernel image):
94``` bash
95$ ls $KERNEL/vmlinux
96$KERNEL/vmlinux
97$ ls $KERNEL/arch/x86/boot/bzImage
98$KERNEL/arch/x86/boot/bzImage
99```
100
101## Image
102
103Install debootstrap:
104``` bash
105sudo apt-get install debootstrap
106```
107
108Use [this script](https://github.com/google/syzkaller/blob/master/tools/create-image.sh) to create a minimal Debian-wheezy Linux image.
109The result should be `$IMAGE/wheezy.img` disk image.
110
111Sometimes it's useful to have some additional packages and tools available in the VM even though they are not required to run syzkaller.
112The instructions to install some useful tools are below.
113They should obviously be executed before packing the `.img` file.
114
115To install other packages (not required to run syzkaller):
116``` bash
117sudo chroot wheezy /bin/bash -c "apt-get update; apt-get install -y curl tar time strace gcc make sysbench git vim screen usbutils"
118```
119
120To install Trinity (not required to run syzkaller):
121``` bash
122sudo chroot wheezy /bin/bash -c "mkdir -p ~; cd ~/; wget https://github.com/kernelslacker/trinity/archive/v1.5.tar.gz -O trinity-1.5.tar.gz; tar -xf trinity-1.5.tar.gz"
123sudo chroot wheezy /bin/bash -c "cd ~/trinity-1.5 ; ./configure.sh ; make -j16 ; make install"
124```
125
126To install perf (not required to run syzkaller):
127``` bash
128cp -r $KERNEL wheezy/tmp/
129sudo chroot wheezy /bin/bash -c "apt-get update; apt-get install -y flex bison python-dev libelf-dev libunwind7-dev libaudit-dev libslang2-dev libperl-dev binutils-dev liblzma-dev libnuma-dev"
130sudo chroot wheezy /bin/bash -c "cd /tmp/linux/tools/perf/; make"
131sudo chroot wheezy /bin/bash -c "cp /tmp/linux/tools/perf/perf /usr/bin/"
132rm -r wheezy/tmp/linux
133```
134
135## QEMU
136
137Install `QEMU`:
138``` bash
139sudo apt-get install kvm qemu-kvm
140```
141
142Make sure the kernel boots and `sshd` starts:
143``` bash
144qemu-system-x86_64 \
145  -kernel $KERNEL/arch/x86/boot/bzImage \
146  -append "console=ttyS0 root=/dev/sda debug earlyprintk=serial slub_debug=QUZ"\
147  -hda $IMAGE/wheezy.img \
148  -net user,hostfwd=tcp::10021-:22 -net nic \
149  -enable-kvm \
150  -nographic \
151  -m 2G \
152  -smp 2 \
153  -pidfile vm.pid \
154  2>&1 | tee vm.log
155```
156
157```
158early console in setup code
159early console in extract_kernel
160input_data: 0x0000000005d9e276
161input_len: 0x0000000001da5af3
162output: 0x0000000001000000
163output_len: 0x00000000058799f8
164kernel_total_size: 0x0000000006b63000
165
166Decompressing Linux... Parsing ELF... done.
167Booting the kernel.
168[    0.000000] Linux version 4.12.0-rc3+ ...
169[    0.000000] Command line: console=ttyS0 root=/dev/sda debug earlyprintk=serial
170...
171[ ok ] Starting enhanced syslogd: rsyslogd.
172[ ok ] Starting periodic command scheduler: cron.
173[ ok ] Starting OpenBSD Secure Shell server: sshd.
174```
175
176After that you should be able to ssh to QEMU instance in another terminal:
177``` bash
178ssh -i $IMAGE/ssh/id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost
179```
180
181If this fails with "too many tries", ssh may be passing default keys before
182the one explicitly passed with `-i`. Append option `-o "IdentitiesOnly yes"`.
183
184To kill the running QEMU instance:
185``` bash
186kill $(cat vm.pid)
187```
188
189## Go
190
191Install Go 1.8.1:
192``` bash
193wget https://storage.googleapis.com/golang/go1.8.1.linux-amd64.tar.gz
194tar -xf go1.8.1.linux-amd64.tar.gz
195mv go goroot
196export GOROOT=`pwd`/goroot
197export PATH=$GOROOT/bin:$PATH
198mkdir gopath
199export GOPATH=`pwd`/gopath
200```
201
202## syzkaller
203
204Get and build syzkaller:
205``` bash
206go get -u -d github.com/google/syzkaller/...
207cd gopath/src/github.com/google/syzkaller/
208mkdir workdir
209make
210```
211
212Create a manager config like the following, replacing the environment
213variables `$GOPATH`, `$KERNEL` and `$IMAGE` with their actual values.
214```
215{
216	"target": "linux/amd64",
217	"http": "127.0.0.1:56741",
218	"workdir": "$GOPATH/src/github.com/google/syzkaller/workdir",
219	"kernel_obj": "$KERNEL",
220	"image": "$IMAGE/wheezy.img",
221	"sshkey": "$IMAGE/ssh/id_rsa",
222	"syzkaller": "$GOPATH/src/github.com/google/syzkaller",
223	"procs": 8,
224	"type": "qemu",
225	"vm": {
226		"count": 4,
227		"kernel": "$KERNEL/arch/x86/boot/bzImage",
228		"cpu": 2,
229		"mem": 2048
230	}
231}
232```
233
234Run syzkaller manager:
235``` bash
236./bin/syz-manager -config=my.cfg
237```
238
239Now syzkaller should be running, you can check manager status with your web browser at `127.0.0.1:56741`.
240
241If you get issues after `syz-manager` starts, consider running it with the `-debug` flag.
242Also see [this page](/docs/troubleshooting.md) for troubleshooting tips.
243