aboutsummaryrefslogtreecommitdiffstats
path: root/docs/fuchsia/setup.sh
blob: d30cd76cd8e4862c43368fabc916f0b861e0c4bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/usr/bin/env bash

# Copyright 2022 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

set -o errexit
set -o errtrace
set -o nounset
set -o pipefail
shopt -s extdebug
IFS=$'\n\t'

# TODO: Make the workdir be a parameter.
# TODO: Scope locals, pass more things as parameters.
# TODO: This script is getting overgrown enough that it's probably time start
# using Go instead.

help="This script will set up, build, and run Syzkaller for Fuchsia. You will
need a Syzkaller checkout and a Fuchsia checkout, and you will need a working
installation of the Go programming language. See docs/fuchsia/README.md in the
Syzkaller repository for more information.

In the commands below, \`syzkaller-directory\` and \`fuchsia-directory\` must be
absolute pathnames.

Usage:

  setup.sh help

Prints this help message.

  setup.sh build syzkaller-directory fuchsia-directory

Builds Syzkaller and Fuchsia for x64.

  setup.sh [-d] run syzkaller-directory fuchsia-directory

Runs Syzkaller on the Fuchsia emulator. (You must have built both first, using
\`setup.sh build ...\`.) If you pass the \`-d\` option, \`syz-manager\` will be
run with the \`--debug\` option.

  setup.sh update syzkaller-directory fuchsia-directory

Updates the Fuchsia system call definitions that Syzkaller will use."

die() {
  echo "$@" > /dev/stderr
  echo "For help, run \`setup.sh help\`."
  exit 1
}

usage() {
  echo "$help"
  exit 0
}

preflight() {
  if ! which go > /dev/null; then
    die "You need to install the Go language."
  fi

  syzkaller="$1"
  if [[ ! -d "$syzkaller" ]]; then
    die "$syzkaller is not a directory."
  fi
  fuchsia="$2"
  if [[ ! -d "$fuchsia" ]]; then
    die "$fuchsia is not a directory."
  fi
}

build() {
  preflight "$syzkaller" "$fuchsia"

  cd "$fuchsia"
  fx --dir "out/x64" set core.x64 \
    --with-base "//bundles/tools" \
    --with-base "//src/testing/fuzzing/syzkaller" \
    --args=syzkaller_dir="\"$syzkaller\"" \
    --variant=kasan
  fx build

  cd "$syzkaller"
  make TARGETOS=fuchsia TARGETARCH=amd64 SOURCEDIR="$fuchsia"
}

run() {
  preflight "$syzkaller" "$fuchsia"

  cd "$fuchsia"

  product_bundle_path="$(ffx config get product.path | tr -d '"')"
  # Look up needed deps from the product bundle assembled
  fxfs_path="$(ffx product get-image-path "$product_bundle_path" --slot a --image-type fxfs)"
  zbi_path="$(ffx product get-image-path "$product_bundle_path" --slot a --image-type zbi)"
  multiboot_path="$(ffx product get-image-path "$product_bundle_path" --slot a --image-type qemu-kernel)"

  # Make sure there are ssh keys available
  ffx config check-ssh-keys
  auth_keys_path="$(ffx config get ssh.pub | tr -d '"')"
  priv_key_path="$(ffx config get ssh.priv | tr -d '"')"

  # Make a separate directory for copies of files we need to modify
  syz_deps_path=$fuchsia/out/x64/syzdeps
  mkdir -p "$syz_deps_path"

  ./out/x64/host_x64/zbi -o "${syz_deps_path}/fuchsia-ssh.zbi" "${zbi_path}" \
    --entry "data/ssh/authorized_keys=${auth_keys_path}"

  cp "$fxfs_path" "${syz_deps_path}/fxfs.blk"

  echo "{
  \"name\": \"fuchsia\",
  \"target\": \"fuchsia/amd64\",
  \"http\": \":12345\",
  \"workdir\": \"$workdir\",
  \"kernel_obj\": \"$fuchsia/out/x64/kernel_x64-kasan/obj/zircon/kernel\",
  \"syzkaller\": \"$syzkaller\",
  \"image\": \"$syz_deps_path/fxfs.blk\",
  \"sshkey\": \"$priv_key_path\",
  \"reproduce\": false,
  \"cover\": false,
  \"procs\": 8,
  \"type\": \"qemu\",
  \"vm\": {
    \"count\": 10,
    \"cpu\": 4,
    \"mem\": 2048,
    \"kernel\": \"$multiboot_path\",
    \"initrd\": \"$syz_deps_path/fuchsia-ssh.zbi\"
  }
}" > "$workdir/fx-syz-manager-config.json"

  cd "$syzkaller"
  # TODO: Find the real way to fix this: Syzkaller wants to invoke qemu
  # manually, but perhaps it should be calling `ffx emu ...` or the like. See
  # also //scripts/hermetic-env and //tools/devshell/lib/prebuilt.sh in
  # $fuchsia.
  PATH="$PATH:$fuchsia/prebuilt/third_party/qemu/linux-x64/bin:$fuchsia/prebuilt/third_party/qemu/mac-x64/bin"
  bin/syz-manager -config "$workdir/fx-syz-manager-config.json" "$debug"
}

update_syscall_definitions() {
  # TODO
  echo "NOTE: This command does not currently work."
  exit

  preflight "$syzkaller" "$fuchsia"

  cd "$syzkaller"
  make extract TARGETOS=fuchsia SOURCEDIR="$fuchsia"
  make generate
}

main() {
  debug=""
  while getopts "d" o; do
    case "$o" in
    d)
      debug="--debug" ;;
    *) ;;
    esac
  done
  shift $((OPTIND - 1))

  if [[ $# != 3 ]]; then
    usage
  fi

  command="$1"
  syzkaller="$2"
  fuchsia="$3"
  workdir="$syzkaller/workdir.fuchsia"
  mkdir -p "$workdir"

  case "$command" in
    build)
      build;;
    run)
      run;;
    update)
      update_syscall_definitions;;
    *)
      usage;;
  esac
}

main "$@"