aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjuanPabloMiceli <48705702+juanPabloMiceli@users.noreply.github.com>2023-01-19 15:59:14 -0500
committerGitHub <noreply@github.com>2023-01-19 15:59:14 -0500
commit551737f1076a910f809cc27ac629c587bc84fc2d (patch)
tree7e847ee19f02e49269ac04437a5e62852aa2bf7e
parent71197f3ac138d7cb03551b7d2159bfc4ecf5c5c2 (diff)
vm/starnix: add support for fuzzing starnix (#3624)
This commit adds a new VM for fuzzing starnix. The VM will boot a fuchsia image using the `ffx` tool and will connect to an adb server inside it. Fuzzing will be done using HostFuzzer mode due to some features not being implemented yet in starnix. Once this is possible, fuzzing will be performed without HostFuzzer mode. Co-authored-by: Juampi Miceli <jpmiceli@google.com>
-rw-r--r--README.md1
-rw-r--r--docs/starnix/README.md66
-rw-r--r--executor/common_linux.h14
-rw-r--r--executor/executor_linux.h4
-rw-r--r--pkg/csource/generated.go14
-rw-r--r--pkg/osutil/osutil.go5
-rw-r--r--pkg/report/report.go3
-rw-r--r--sys/targets/targets.go6
-rw-r--r--vm/starnix/starnix.go361
-rw-r--r--vm/vm.go25
-rw-r--r--vm/vmimpl/vmimpl.go21
11 files changed, 484 insertions, 36 deletions
diff --git a/README.md b/README.md
index 6caf5a3c4..607147fd5 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@ For other OS kernels check:
[Fuchsia](docs/fuchsia/README.md),
[NetBSD](docs/netbsd/README.md),
[OpenBSD](docs/openbsd/setup.md),
+[Starnix](docs/starnix/README.md),
[Windows](docs/windows/README.md),
[gVisor](docs/gvisor/README.md).
diff --git a/docs/starnix/README.md b/docs/starnix/README.md
new file mode 100644
index 000000000..dac148d80
--- /dev/null
+++ b/docs/starnix/README.md
@@ -0,0 +1,66 @@
+# starnix support
+
+## Prerequisites
+
+To run syzkaller for fuzzing starnix, you will need a checkout of the Fuchsia
+source repository.
+
+The rest of this document will use the environment variable `SOURCEDIR` to
+identify the path to your Fuchsia checkout (e.g. `/home/you/fuchsia`). The
+commands below assume you have set `SOURCEDIR`, like so:
+
+```bash
+export SOURCEDIR=/home/you/fuchsia
+```
+
+To build Fuchsia for qemu-x64, run:
+```
+fx --dir "out/qemu-x64" set workstation_eng.qemu-x64 \
+ --with "//bundles/tools" \
+ --with "//src/proc/bin/starnix"
+fx build
+```
+
+You will also need to follow the instructions in the sections `GCC` and `Kernel`
+of the [setup\_ubuntu-host\_qemu-vm\_x86-64-kernel.md](../linux/setup_ubuntu-host_qemu-vm_x86-64-kernel.md) file.
+
+
+## syzkaller
+
+### Building binaries for starnix
+First, you need to build all the binaries required for running syzkaller in starnix.
+For that, you only need to run this from inside your syzkaller checkout (assuming you built Fuchsia for x64):
+
+```bash
+SYZ_STARNIX_HACK=1 make TARGETOS=linux TARGETARCH=amd64
+```
+
+### Configuration file
+Create a manager config like the following, replacing the environment variables `$SYZKALLER`, `$KERNEL` and `$IMAGE` with their actual values.
+
+> **_NOTE:_** `ffx` is still under development, for that reason VM count of 1 is recommended until fxbug.dev/118926 is solved.
+
+```bash
+{
+ "target": "linux/amd64",
+ "http": "127.0.0.1:56741",
+ "workdir": "$SYZKALLER/workdir",
+ "kernel_obj": "$KERNEL",
+ "kernel_src": "$SOURCEDIR",
+ "syzkaller": "$SYZKALLER",
+ "procs": 8,
+ "type": "starnix",
+ "vm": {
+ "count": 1,
+ },
+ "cover": false
+}
+```
+
+### Running
+
+Lastly, just run the command below to start fuzzing.
+
+```bash
+SYZ_STARNIX_HACK=1 bin/syz-manager -config=./starnix.cfg
+```
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 64e3f8fb5..06d94fe67 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -2271,7 +2271,7 @@ static long syz_memcpy_off(volatile long a0, volatile long a1, volatile long a2,
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_NET_INJECTION
+#if (SYZ_EXECUTOR || SYZ_REPEAT && SYZ_NET_INJECTION) && SYZ_EXECUTOR_USES_FORK_SERVER
static void flush_tun()
{
#if SYZ_EXECUTOR
@@ -3119,7 +3119,7 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat
#endif
#endif
-#if SYZ_EXECUTOR || SYZ_NET_RESET
+#if (SYZ_EXECUTOR || SYZ_NET_RESET) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -3698,7 +3698,7 @@ static void setup_cgroups()
write_file("/syzcgroup/cpu/cpuset.memory_pressure_enabled", "1");
}
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
static void setup_cgroups_loop()
{
#if SYZ_EXECUTOR
@@ -4597,7 +4597,7 @@ static int fault_injected(int fail_fd)
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -4654,7 +4654,7 @@ static void kill_and_wait(int pid, int* status)
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_CGROUPS || SYZ_NET_RESET)
+#if (SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_CGROUPS || SYZ_NET_RESET)) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
@@ -4673,7 +4673,7 @@ static void setup_loop()
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_NET_RESET || __NR_syz_mount_image || __NR_syz_read_part_table)
+#if (SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_NET_RESET || __NR_syz_mount_image || __NR_syz_read_part_table)) && SYZ_EXECUTOR_USES_FORK_SERVER
#define SYZ_HAVE_RESET_LOOP 1
static void reset_loop()
{
@@ -4692,7 +4692,7 @@ static void reset_loop()
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <sys/prctl.h>
#include <unistd.h>
diff --git a/executor/executor_linux.h b/executor/executor_linux.h
index 54246bda9..630ceb81f 100644
--- a/executor/executor_linux.h
+++ b/executor/executor_linux.h
@@ -95,9 +95,11 @@ static void cover_protect(cover_t* cov)
{
}
+#if SYZ_EXECUTOR_USES_SHMEM
static void cover_unprotect(cover_t* cov)
{
}
+#endif
static void cover_mmap(cover_t* cov)
{
@@ -158,6 +160,7 @@ static void cover_collect(cover_t* cov)
cov->size = *(uint32*)cov->data;
}
+#if SYZ_EXECUTOR_USES_SHMEM
static bool use_cover_edges(uint32 pc)
{
return true;
@@ -176,6 +179,7 @@ static bool use_cover_edges(uint64 pc)
#endif
return true;
}
+#endif
static bool detect_kernel_bitness()
{
diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go
index 955d7c971..3921d1b6e 100644
--- a/pkg/csource/generated.go
+++ b/pkg/csource/generated.go
@@ -4378,7 +4378,7 @@ static long syz_memcpy_off(volatile long a0, volatile long a1, volatile long a2,
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT && SYZ_NET_INJECTION
+#if (SYZ_EXECUTOR || SYZ_REPEAT && SYZ_NET_INJECTION) && SYZ_EXECUTOR_USES_FORK_SERVER
static void flush_tun()
{
#if SYZ_EXECUTOR
@@ -8173,7 +8173,7 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat
#endif
#endif
-#if SYZ_EXECUTOR || SYZ_NET_RESET
+#if (SYZ_EXECUTOR || SYZ_NET_RESET) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -8719,7 +8719,7 @@ static void setup_cgroups()
write_file("/syzcgroup/cpu/cpuset.memory_pressure_enabled", "1");
}
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
static void setup_cgroups_loop()
{
#if SYZ_EXECUTOR
@@ -10542,7 +10542,7 @@ static int fault_injected(int fail_fd)
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -10592,7 +10592,7 @@ static void kill_and_wait(int pid, int* status)
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_CGROUPS || SYZ_NET_RESET)
+#if (SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_CGROUPS || SYZ_NET_RESET)) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
@@ -10611,7 +10611,7 @@ static void setup_loop()
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_NET_RESET || __NR_syz_mount_image || __NR_syz_read_part_table)
+#if (SYZ_EXECUTOR || SYZ_REPEAT && (SYZ_NET_RESET || __NR_syz_mount_image || __NR_syz_read_part_table)) && SYZ_EXECUTOR_USES_FORK_SERVER
#define SYZ_HAVE_RESET_LOOP 1
static void reset_loop()
{
@@ -10630,7 +10630,7 @@ static void reset_loop()
}
#endif
-#if SYZ_EXECUTOR || SYZ_REPEAT
+#if (SYZ_EXECUTOR || SYZ_REPEAT) && SYZ_EXECUTOR_USES_FORK_SERVER
#include <sys/prctl.h>
#include <unistd.h>
diff --git a/pkg/osutil/osutil.go b/pkg/osutil/osutil.go
index c07c6372b..6ac96b344 100644
--- a/pkg/osutil/osutil.go
+++ b/pkg/osutil/osutil.go
@@ -130,6 +130,11 @@ func PrependContext(ctx string, err error) error {
}
}
+func IsDir(name string) bool {
+ fileInfo, err := os.Stat(name)
+ return err == nil && fileInfo.IsDir()
+}
+
// IsExist returns true if the file name exists.
func IsExist(name string) bool {
_, err := os.Stat(name)
diff --git a/pkg/report/report.go b/pkg/report/report.go
index 8a710e062..7dd9714b3 100644
--- a/pkg/report/report.go
+++ b/pkg/report/report.go
@@ -101,7 +101,7 @@ func (t Type) String() string {
// NewReporter creates reporter for the specified OS/Type.
func NewReporter(cfg *mgrconfig.Config) (*Reporter, error) {
typ := cfg.TargetOS
- if cfg.Type == "gvisor" {
+ if cfg.Type == "gvisor" || cfg.Type == "starnix" {
typ = cfg.Type
}
ctor := ctors[typ]
@@ -151,6 +151,7 @@ const (
var ctors = map[string]fn{
targets.Akaros: ctorAkaros,
targets.Linux: ctorLinux,
+ "starnix": ctorFuchsia,
"gvisor": ctorGvisor,
targets.FreeBSD: ctorFreebsd,
targets.Darwin: ctorDarwin,
diff --git a/sys/targets/targets.go b/sys/targets/targets.go
index 1e19cfe88..c891df41b 100644
--- a/sys/targets/targets.go
+++ b/sys/targets/targets.go
@@ -726,6 +726,12 @@ func initTarget(target *Target, OS, arch string) {
} else {
target.HostEndian = binary.BigEndian
}
+ // Temporal hack.
+ if OS == Linux && os.Getenv("SYZ_STARNIX_HACK") != "" {
+ target.ExecutorUsesShmem = false
+ target.ExecutorUsesForkServer = false
+ target.HostFuzzer = true
+ }
}
func (target *Target) Timeouts(slowdown int) Timeouts {
diff --git a/vm/starnix/starnix.go b/vm/starnix/starnix.go
new file mode 100644
index 000000000..f868284b2
--- /dev/null
+++ b/vm/starnix/starnix.go
@@ -0,0 +1,361 @@
+// Copyright 2023 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.
+
+package starnix
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/google/syzkaller/pkg/config"
+ "github.com/google/syzkaller/pkg/log"
+ "github.com/google/syzkaller/pkg/osutil"
+ "github.com/google/syzkaller/pkg/report"
+ "github.com/google/syzkaller/vm/vmimpl"
+)
+
+func init() {
+ var _ vmimpl.Infoer = (*instance)(nil)
+ vmimpl.Register("starnix", ctor, true)
+}
+
+type Config struct {
+ // Number of VMs to run in parallel (1 by default).
+ Count int `json:"count"`
+}
+
+type Pool struct {
+ count int
+ env *vmimpl.Env
+ cfg *Config
+}
+
+type instance struct {
+ fuchsiaDirectory string
+ name string
+ index int
+ cfg *Config
+ version string
+ debug bool
+ workdir string
+ port int
+ rpipe io.ReadCloser
+ wpipe io.WriteCloser
+ fuchsiaLogs *exec.Cmd
+ adb *exec.Cmd
+ executor string
+ merger *vmimpl.OutputMerger
+ diagnose chan bool
+}
+
+const ffxBinary = ".jiri_root/bin/ffx"
+const targetDir = "/data"
+
+func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
+ cfg := &Config{}
+ if err := config.LoadData(env.Config, cfg); err != nil {
+ return nil, fmt.Errorf("failed to parse starnix vm config: %v", err)
+ }
+ if cfg.Count < 1 || cfg.Count > 128 {
+ return nil, fmt.Errorf("invalid config param count: %v, want [1, 128]", cfg.Count)
+ }
+ if _, err := exec.LookPath("adb"); err != nil {
+ return nil, err
+ }
+
+ pool := &Pool{
+ count: cfg.Count,
+ env: env,
+ cfg: cfg,
+ }
+ return pool, nil
+}
+
+func (pool *Pool) Count() int {
+ return pool.count
+}
+
+func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
+ inst := &instance{
+ fuchsiaDirectory: pool.env.KernelSrc,
+ name: fmt.Sprintf("VM-%v", index),
+ index: index,
+ cfg: pool.cfg,
+ debug: pool.env.Debug,
+ workdir: workdir,
+ // This file is auto-generated inside createAdbScript.
+ executor: filepath.Join(workdir, "adb_executor.sh"),
+ }
+ closeInst := inst
+ defer func() {
+ if closeInst != nil {
+ closeInst.Close()
+ }
+ }()
+
+ var err error
+ inst.rpipe, inst.wpipe, err = osutil.LongPipe()
+ if err != nil {
+ return nil, err
+ }
+
+ if err := inst.setFuchsiaVersion(); err != nil {
+ return nil, fmt.Errorf(
+ "there is an error running ffx commands in the Fuchsia checkout (%q): %v",
+ inst.fuchsiaDirectory,
+ err)
+ }
+
+ if err := inst.boot(); err != nil {
+ return nil, err
+ }
+
+ closeInst = nil
+ return inst, nil
+}
+
+func (inst *instance) boot() error {
+ inst.port = vmimpl.UnusedTCPPort()
+ // Start output merger.
+ inst.merger = vmimpl.NewOutputMerger(nil)
+
+ inst.ffx("doctor", "--restart-daemon")
+
+ inst.ffx("emu", "stop", inst.name)
+
+ if err := inst.startFuchsiaVM(); err != nil {
+ return fmt.Errorf("could not start Fuchsia VM: %v", err)
+ }
+
+ if err := inst.startAdbServerAndConnection(1 * time.Minute); err != nil {
+ return fmt.Errorf("could not start and connect to the adb server: %v", err)
+ }
+
+ if err := inst.createAdbScript(); err != nil {
+ return fmt.Errorf("could not create adb script: %v", err)
+ }
+
+ err := inst.startFuchsiaLogs()
+ if err != nil {
+ return fmt.Errorf("could not start fuchsia logs: %v", err)
+ }
+ if inst.debug {
+ log.Logf(0, "%s booted successfully", inst.name)
+ }
+ return nil
+}
+
+func (inst *instance) Close() {
+ inst.ffx("emu", "stop", inst.name)
+ if inst.fuchsiaLogs != nil {
+ inst.fuchsiaLogs.Process.Kill()
+ inst.fuchsiaLogs.Wait()
+ }
+ if inst.adb != nil {
+ inst.adb.Process.Kill()
+ inst.adb.Wait()
+ }
+ if inst.merger != nil {
+ inst.merger.Wait()
+ }
+ if inst.rpipe != nil {
+ inst.rpipe.Close()
+ }
+ if inst.wpipe != nil {
+ inst.wpipe.Close()
+ }
+}
+
+func (inst *instance) startFuchsiaVM() error {
+ err := inst.ffx("emu", "start", "--headless", "--name", inst.name)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (inst *instance) startFuchsiaLogs() error {
+ cmd := osutil.Command(ffxBinary, "--target", inst.name, "log")
+ cmd.Dir = inst.fuchsiaDirectory
+ cmd.Stdout = inst.wpipe
+ cmd.Stderr = inst.wpipe
+ inst.merger.Add("fuchsia", inst.rpipe)
+ inst.fuchsiaLogs = cmd
+ return cmd.Start()
+}
+
+func (inst *instance) startAdbServerAndConnection(timeout time.Duration) error {
+ cmd := osutil.Command(ffxBinary, "--target", inst.name, "starnix", "adb", "-p", fmt.Sprintf("%d", inst.port))
+ cmd.Dir = inst.fuchsiaDirectory
+ if err := cmd.Start(); err != nil {
+ return err
+ }
+ if inst.debug {
+ log.Logf(0, fmt.Sprintf("the adb bridge is listening on 127.0.0.1:%d", inst.port))
+ }
+ inst.adb = cmd
+ return inst.connectToAdb(timeout)
+}
+
+func (inst *instance) connectToAdb(timeout time.Duration) error {
+ startTime := time.Now()
+ for {
+ vmimpl.SleepInterruptible(3 * time.Second)
+ if inst.debug {
+ log.Logf(0, "attempting to connect to ADB")
+ }
+ connectOutput, err := osutil.RunCmd(
+ 2*time.Minute,
+ inst.fuchsiaDirectory,
+ "adb",
+ "connect",
+ fmt.Sprintf("127.0.0.1:%d", inst.port))
+ if err == nil && strings.HasPrefix(string(connectOutput), "connected to") {
+ return nil
+ }
+ inst.runCommand("adb", "disconnect", fmt.Sprintf("127.0.0.1:%d", inst.port))
+ if inst.debug {
+ log.Logf(0, "adb connect failed")
+ }
+ if time.Since(startTime) > timeout {
+ return fmt.Errorf("can't connect to ADB server")
+ }
+ }
+}
+
+// Script for telling syz-fuzzer how to connect to syz-executor.
+func (inst *instance) createAdbScript() error {
+ adbScript := fmt.Sprintf(
+ `#!/bin/bash
+ adb_port=$1
+ fuzzer_args=${@:2}
+ adb -s 127.0.0.1:$adb_port shell "cd %s; ./syz-executor $fuzzer_args"`, targetDir)
+ return os.WriteFile(inst.executor, []byte(adbScript), 0777)
+}
+
+func (inst *instance) ffx(args ...string) error {
+ return inst.runCommand(ffxBinary, args...)
+}
+
+// Runs a command inside the fuchsia directory.
+func (inst *instance) runCommand(cmd string, args ...string) error {
+ if inst.debug {
+ log.Logf(0, "running command: %s %q", cmd, args)
+ }
+ output, err := osutil.RunCmd(5*time.Minute, inst.fuchsiaDirectory, cmd, args...)
+ if inst.debug {
+ log.Logf(0, "%s", output)
+ }
+ return err
+}
+
+func (inst *instance) Forward(port int) (string, error) {
+ if port == 0 {
+ return "", fmt.Errorf("vm/starnix: forward port is zero")
+ }
+ return fmt.Sprintf("localhost:%v", port), nil
+}
+
+func (inst *instance) Copy(hostSrc string) (string, error) {
+ base := filepath.Base(hostSrc)
+ vmDst := filepath.Join(targetDir, base)
+ if base == "syz-fuzzer" || base == "syz-execprog" {
+ return hostSrc, nil // we will run these on host.
+ }
+
+ err := inst.runCommand(
+ "adb",
+ "-s",
+ fmt.Sprintf("127.0.0.1:%d", inst.port),
+ "push",
+ hostSrc,
+ vmDst)
+ return vmDst, err
+}
+
+func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command string) (
+ <-chan []byte, <-chan error, error) {
+ rpipe, wpipe, err := osutil.LongPipe()
+ if err != nil {
+ return nil, nil, err
+ }
+ inst.merger.Add("adb", rpipe)
+
+ args := strings.Split(command, " ")
+ if bin := filepath.Base(args[0]); bin == "syz-fuzzer" || bin == "syz-execprog" {
+ for i, arg := range args {
+ if strings.HasPrefix(arg, "-executor=") {
+ args[i] = fmt.Sprintf("-executor=%s %d", inst.executor, inst.port)
+ // TODO(fxbug.dev/120202): reenable threaded mode once clone3 is fixed.
+ args = append(args, "-threaded=0")
+ }
+ }
+ }
+ if inst.debug {
+ log.Logf(0, "running command: %#v", args)
+ }
+ cmd := osutil.Command(args[0], args[1:]...)
+ cmd.Dir = inst.workdir
+ cmd.Stdout = wpipe
+ cmd.Stderr = wpipe
+ if err := cmd.Run(); err != nil {
+ wpipe.Close()
+ return nil, nil, err
+ }
+ wpipe.Close()
+ errc := make(chan error, 1)
+ signal := func(err error) {
+ select {
+ case errc <- err:
+ default:
+ }
+ }
+
+ go func() {
+ retry:
+ select {
+ case <-time.After(timeout):
+ signal(vmimpl.ErrTimeout)
+ case <-stop:
+ signal(vmimpl.ErrTimeout)
+ case <-inst.diagnose:
+ cmd.Process.Kill()
+ goto retry
+ case err := <-inst.merger.Err:
+ cmd.Process.Kill()
+ if cmdErr := cmd.Wait(); cmdErr == nil {
+ // If the command exited successfully, we got EOF error from merger.
+ // But in this case no error has happened and the EOF is expected.
+ err = nil
+ }
+ signal(err)
+ return
+ }
+ cmd.Process.Kill()
+ cmd.Wait()
+ }()
+ return inst.merger.Output, errc, nil
+}
+
+func (inst *instance) Info() ([]byte, error) {
+ info := fmt.Sprintf("%v\n%v", inst.version, "ffx")
+ return []byte(info), nil
+}
+
+func (inst *instance) Diagnose(rep *report.Report) ([]byte, bool) {
+ return nil, false
+}
+
+func (inst *instance) setFuchsiaVersion() error {
+ version, err := osutil.RunCmd(1*time.Minute, inst.fuchsiaDirectory, ffxBinary, "version")
+ if err != nil {
+ return err
+ }
+ inst.version = string(version)
+ return nil
+}
diff --git a/vm/vm.go b/vm/vm.go
index c56211081..c340dfbf6 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -34,6 +34,7 @@ import (
_ "github.com/google/syzkaller/vm/odroid"
_ "github.com/google/syzkaller/vm/proxyapp"
_ "github.com/google/syzkaller/vm/qemu"
+ _ "github.com/google/syzkaller/vm/starnix"
_ "github.com/google/syzkaller/vm/vmm"
_ "github.com/google/syzkaller/vm/vmware"
)
@@ -83,16 +84,17 @@ func Create(cfg *mgrconfig.Config, debug bool) (*Pool, error) {
return nil, fmt.Errorf("unknown instance type '%v'", cfg.Type)
}
env := &vmimpl.Env{
- Name: cfg.Name,
- OS: cfg.TargetOS,
- Arch: cfg.TargetVMArch,
- Workdir: cfg.Workdir,
- Image: cfg.Image,
- SSHKey: cfg.SSHKey,
- SSHUser: cfg.SSHUser,
- Timeouts: cfg.Timeouts,
- Debug: debug,
- Config: cfg.VM,
+ Name: cfg.Name,
+ OS: cfg.TargetOS,
+ Arch: cfg.TargetVMArch,
+ Workdir: cfg.Workdir,
+ Image: cfg.Image,
+ SSHKey: cfg.SSHKey,
+ SSHUser: cfg.SSHUser,
+ Timeouts: cfg.Timeouts,
+ Debug: debug,
+ Config: cfg.VM,
+ KernelSrc: cfg.KernelSrc,
}
impl, err := typ.Ctor(env)
if err != nil {
@@ -139,7 +141,8 @@ func (pool *Pool) Create(index int) (*Instance, error) {
}
// TODO: Integration or end-to-end testing is needed.
-// https://github.com/google/syzkaller/pull/3269#discussion_r967650801
+//
+// https://github.com/google/syzkaller/pull/3269#discussion_r967650801
func (pool *Pool) Close() error {
if pool.activeCount != 0 {
panic("all the instances should be closed before pool.Close()")
diff --git a/vm/vmimpl/vmimpl.go b/vm/vmimpl/vmimpl.go
index 5ec84b35d..10de2ffed 100644
--- a/vm/vmimpl/vmimpl.go
+++ b/vm/vmimpl/vmimpl.go
@@ -71,16 +71,17 @@ type Infoer interface {
type Env struct {
// Unique name
// Can be used for VM name collision resolution if several pools share global name space.
- Name string
- OS string // target OS
- Arch string // target arch
- Workdir string
- Image string
- SSHKey string
- SSHUser string
- Timeouts targets.Timeouts
- Debug bool
- Config []byte // json-serialized VM-type-specific config
+ Name string
+ OS string // target OS
+ Arch string // target arch
+ Workdir string
+ Image string
+ SSHKey string
+ SSHUser string
+ Timeouts targets.Timeouts
+ Debug bool
+ Config []byte // json-serialized VM-type-specific config
+ KernelSrc string
}
// BootError is returned by Pool.Create when VM does not boot.