github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/docs/linux/setup_ubuntu-host_qemu-vm_x86-64-kernel.md (about)

     1  # Setup: Ubuntu host, QEMU vm, x86-64 kernel
     2  
     3  These are the instructions on how to fuzz the x86-64 kernel in a QEMU with Ubuntu on the host machine and Debian Bullseye in the QEMU instances.
     4  
     5  In the instructions below, the `$VAR` notation (e.g. `$GCC`, `$KERNEL`, etc.) is used to denote paths to directories that are either created when executing the instructions (e.g. when unpacking GCC archive, a directory will be created), or that you have to create yourself before running the instructions. Substitute the values for those variables manually.
     6  
     7  
     8  ## Install Prerequisites
     9  
    10  Command:
    11  ``` bash
    12  sudo apt update
    13  sudo apt install make gcc flex bison libncurses-dev libelf-dev libssl-dev
    14  ```
    15  
    16  
    17  ## GCC
    18  
    19  If your distro's GCC is older, it's preferable to get the latest GCC from [this](/docs/syzbot.md#crash-does-not-reproduce) list. Download and unpack into `$GCC`, and you should have GCC binaries in `$GCC/bin/`
    20  
    21  >**Ubuntu 20.04 LTS**: You can ignore this section. GCC is up-to-date.
    22  
    23  Command:
    24  ``` bash
    25  ls $GCC/bin/
    26  # Sample output:
    27  # cpp     gcc-ranlib  x86_64-pc-linux-gnu-gcc        x86_64-pc-linux-gnu-gcc-ranlib
    28  # gcc     gcov        x86_64-pc-linux-gnu-gcc-9.0.0
    29  # gcc-ar  gcov-dump   x86_64-pc-linux-gnu-gcc-ar
    30  # gcc-nm  gcov-tool   x86_64-pc-linux-gnu-gcc-nm
    31  ```
    32  
    33  ## Kernel
    34  
    35  ### Checkout Linux Kernel source
    36  
    37  Command:
    38  ``` bash
    39  git clone --branch v6.2 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $KERNEL
    40  ```
    41  
    42  >We recommend to start with the latest stable version. v6.2 is an example here.
    43  
    44  ### Generate default configs
    45  
    46  Command:
    47  ``` bash
    48  cd $KERNEL
    49  make defconfig
    50  make kvm_guest.config
    51  ```
    52  
    53  Or if you want to specify a compiler.
    54  
    55  Command:
    56  ``` bash
    57  cd $KERNEL
    58  make CC="$GCC/bin/gcc" defconfig
    59  make CC="$GCC/bin/gcc" kvm_guest.config
    60  ```
    61  
    62  ### Enable required config options
    63  
    64  Enable kernel config options required for syzkaller as described [here](kernel_configs.md).
    65  It's not required to enable all of them, but at the very least you need:
    66  
    67  ``` make
    68  # Coverage collection.
    69  CONFIG_KCOV=y
    70  
    71  # Debug info for symbolization.
    72  CONFIG_DEBUG_INFO_DWARF4=y
    73  
    74  # Memory bug detector
    75  CONFIG_KASAN=y
    76  CONFIG_KASAN_INLINE=y
    77  
    78  # Required for Debian Stretch and later
    79  CONFIG_CONFIGFS_FS=y
    80  CONFIG_SECURITYFS=y
    81  ```
    82  
    83  Edit `.config` file manually and enable them (or do that through `make menuconfig` if you prefer).
    84  
    85  Since enabling these options results in more sub options being available, we need to regenerate config:
    86  
    87  Command:
    88  ``` bash
    89  make olddefconfig
    90  ```
    91  
    92  Or if you want to specify a compiler.
    93  
    94  Command:
    95  ``` bash
    96  make CC="$GCC/bin/gcc" olddefconfig
    97  ```
    98  
    99  You might also be interested in disabling the Predictable Network Interface Names mechanism. This can be disabled either in the syzkaller configuration (see details [here](troubleshooting.md)) or by updating these kernel configuration parameters:
   100  
   101  ``` make
   102  CONFIG_CMDLINE_BOOL=y
   103  CONFIG_CMDLINE="net.ifnames=0"
   104  ```
   105  
   106  ### Build the Kernel
   107  
   108  Command:
   109  ``` bash
   110  make -j`nproc`
   111  ```
   112  
   113  Or if you want to specify a compiler.
   114  
   115  Command:
   116  ``` bash
   117  make CC="$GCC/bin/gcc" -j`nproc`
   118  ```
   119  
   120  Now you should have `vmlinux` (kernel binary) and `bzImage` (packed kernel image):
   121  
   122  Command:
   123  ``` bash
   124  ls $KERNEL/vmlinux
   125  # sample output - $KERNEL/vmlinux
   126  ls $KERNEL/arch/x86/boot/bzImage
   127  # sample output - $KERNEL/arch/x86/boot/bzImage
   128  ```
   129  
   130  ## Image
   131  
   132  ### Install debootstrap
   133  
   134  Command:
   135  ``` bash
   136  sudo apt install debootstrap
   137  ```
   138  
   139  ### Create Debian Bullseye Linux image
   140  
   141  Create a Debian Bullseye Linux image with the minimal set of required packages.
   142  
   143  Command:
   144  ``` bash
   145  mkdir $IMAGE
   146  cd $IMAGE/
   147  wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
   148  chmod +x create-image.sh
   149  ./create-image.sh
   150  ```
   151  
   152  The result should be `$IMAGE/bullseye.img` disk image.
   153  
   154  ### OR Create Debian Linux image with a different version
   155  
   156  To create a Debian image with a different version (e.g. buster, stretch, sid), specify the `--distribution` option.
   157  
   158  Command:
   159  ``` bash
   160  ./create-image.sh --distribution buster
   161  ```
   162  
   163  ### Image extra tools
   164  
   165  Sometimes it's useful to have some additional packages and tools available in the VM even though they are not required to run syzkaller. To install a set of tools we find useful do (feel free to edit the list of tools in the script):
   166  
   167  Command:
   168  ``` bash
   169  ./create-image.sh --feature full
   170  ```
   171  
   172  To install perf (not required to run syzkaller; requires `$KERNEL` to point to the kernel sources):
   173  
   174  Command:
   175  ``` bash
   176  ./create-image.sh --add-perf
   177  ```
   178  
   179  For additional options of `create-image.sh`, please refer to `./create-image.sh -h`
   180  
   181  ## QEMU
   182  
   183  ### Install QEMU
   184  
   185  Command:
   186  ``` bash
   187  sudo apt install qemu-system-x86
   188  ```
   189  
   190  ### Verify
   191  
   192  Make sure the kernel boots and `sshd` starts.
   193  
   194  Command:
   195  ``` bash
   196  qemu-system-x86_64 \
   197  	-m 2G \
   198  	-smp 2 \
   199  	-kernel $KERNEL/arch/x86/boot/bzImage \
   200  	-append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
   201  	-drive file=$IMAGE/bullseye.img,format=raw \
   202  	-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
   203  	-net nic,model=e1000 \
   204  	-enable-kvm \
   205  	-nographic \
   206  	-pidfile vm.pid \
   207  	2>&1 | tee vm.log
   208  ```
   209  
   210  ``` text
   211  early console in setup code
   212  early console in extract_kernel
   213  input_data: 0x0000000005d9e276
   214  input_len: 0x0000000001da5af3
   215  output: 0x0000000001000000
   216  output_len: 0x00000000058799f8
   217  kernel_total_size: 0x0000000006b63000
   218  
   219  Decompressing Linux... Parsing ELF... done.
   220  Booting the kernel.
   221  [    0.000000] Linux version 4.12.0-rc3+ ...
   222  [    0.000000] Command line: console=ttyS0 root=/dev/sda debug earlyprintk=serial
   223  ...
   224  [ ok ] Starting enhanced syslogd: rsyslogd.
   225  [ ok ] Starting periodic command scheduler: cron.
   226  [ ok ] Starting OpenBSD Secure Shell server: sshd.
   227  ```
   228  
   229  After that you should be able to ssh to QEMU instance in another terminal.
   230  
   231  Command:
   232  ``` bash
   233  ssh -i $IMAGE/bullseye.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost
   234  ```
   235  
   236  ### Troubleshooting
   237  
   238  If this fails with "too many tries", ssh may be passing default keys before
   239  the one explicitly passed with `-i`. Append option `-o "IdentitiesOnly yes"`.
   240  
   241  To kill the running QEMU instance press `Ctrl+A` and then `X` or run:
   242  
   243  Command:
   244  ``` bash
   245  kill $(cat vm.pid)
   246  ```
   247  
   248  If QEMU works, the kernel boots and ssh succeeds, you can shutdown QEMU and try to run syzkaller.
   249  
   250  ## syzkaller
   251  
   252  Build syzkaller as described [here](/docs/linux/setup.md#go-and-syzkaller).
   253  Then create a manager config like the following, replacing the environment
   254  variables `$GOPATH`, `$KERNEL` and `$IMAGE` with their actual values.
   255  
   256  ``` json
   257  {
   258  	"target": "linux/amd64",
   259  	"http": "127.0.0.1:56741",
   260  	"workdir": "$GOPATH/src/github.com/google/syzkaller/workdir",
   261  	"kernel_obj": "$KERNEL",
   262  	"image": "$IMAGE/bullseye.img",
   263  	"sshkey": "$IMAGE/bullseye.id_rsa",
   264  	"syzkaller": "$GOPATH/src/github.com/google/syzkaller",
   265  	"procs": 8,
   266  	"type": "qemu",
   267  	"vm": {
   268  		"count": 4,
   269  		"kernel": "$KERNEL/arch/x86/boot/bzImage",
   270  		"cpu": 2,
   271  		"mem": 2048
   272  	}
   273  }
   274  ```
   275  
   276  Run syzkaller manager:
   277  
   278  ``` bash
   279  mkdir workdir
   280  ./bin/syz-manager -config=my.cfg
   281  ```
   282  
   283  Now syzkaller should be running, you can check manager status with your web browser at `127.0.0.1:56741`.
   284  
   285  If you get issues after `syz-manager` starts, consider running it with the `-debug` flag.
   286  Also see [this page](/docs/troubleshooting.md) for troubleshooting tips.