blob: d30cd76cd8e4862c43368fabc916f0b861e0c4bf [file] [log] [blame]
#!/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 "$@"