From f3762ee614bce38772288104d514e80d779996da Mon Sep 17 00:00:00 2001 From: Laura Peskin Date: Wed, 18 Jun 2025 16:03:30 -0700 Subject: vm/starnix: copy sdk overrides to isolated ffx config ffx emu now needs to know the locations of some host tools. Copy these paths from the default ffx config into the configuration for the isolated ffx instance that syzkaller uses for most tasks. --- vm/starnix/starnix.go | 101 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 27 deletions(-) (limited to 'vm') diff --git a/vm/starnix/starnix.go b/vm/starnix/starnix.go index c1921aff5..98d44d3ff 100644 --- a/vm/starnix/starnix.go +++ b/vm/starnix/starnix.go @@ -12,6 +12,7 @@ import ( "os" "os/exec" "path/filepath" + "slices" "strconv" "strings" "time" @@ -133,30 +134,24 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { inst.fuchsiaDir, err) } - pubkey, err := inst.runFfx(30*time.Second, "config", "get", "ssh.pub") + pubkey, err := inst.getFfxConfigValue("ssh.pub") if err != nil { return nil, err } - inst.sshPubKey = string(bytes.Trim(pubkey, "\"\n")) - privkey, err := inst.runFfx(30*time.Second, "config", "get", "ssh.priv") - if err != nil { - return nil, err - } - inst.sshPrivKey = string(bytes.Trim(privkey, "\"\n")) + inst.sshPubKey = pubkey - // Copy auto-detected product bundle path from in-tree ffx to isolated ffx. - cmd := osutil.Command(inst.ffxBinary, - "-c", "log.enabled=false,ffx.analytics.disabled=true,daemon.autostart=false", - "config", "get", "product.path") - cmd.Env = append(cmd.Environ(), "FUCHSIA_ANALYTICS_DISABLED=1") - cmd.Dir = inst.fuchsiaDir - output, err := osutil.Run(30*time.Second, cmd) + privkey, err := inst.getFfxConfigValue("ssh.priv") if err != nil { return nil, err } - pbPath := string(bytes.Trim(output, "\"\n")) + inst.sshPrivKey = privkey - if _, err := inst.runFfx(30*time.Second, "config", "set", "product.path", pbPath); err != nil { + // Copy auto-detected paths from in-tree ffx to isolated ffx. + err = inst.copyFfxConfigValuesToIsolate( + "product.path", + "sdk.overrides.aemu_internal", + "sdk.overrides.uefi_internal_x64") + if err != nil { return nil, err } @@ -186,7 +181,7 @@ func (inst *instance) boot() error { } inst.merger = vmimpl.NewOutputMerger(tee) - inst.runFfx(5*time.Minute, "emu", "stop", inst.name) + inst.runFfx(5*time.Minute, true, "emu", "stop", inst.name) if err := inst.startFuchsiaVM(); err != nil { return fmt.Errorf("instance %s: could not start Fuchsia VM: %w", inst.name, err) @@ -207,7 +202,7 @@ func (inst *instance) boot() error { } func (inst *instance) Close() error { - inst.runFfx(5*time.Minute, "emu", "stop", inst.name) + inst.runFfx(5*time.Minute, true, "emu", "stop", inst.name) if inst.fuchsiaLogs != nil { inst.fuchsiaLogs.Process.Kill() inst.fuchsiaLogs.Wait() @@ -229,8 +224,10 @@ func (inst *instance) Close() error { } func (inst *instance) startFuchsiaVM() error { - inst.runFfx(30*time.Second, "config", "get", "product.path") - if _, err := inst.runFfx(5*time.Minute, "emu", "start", "--headless", + if _, err := inst.runFfx( + 5*time.Minute, + true, + "emu", "start", "--headless", "--name", inst.name, "--net", "user"); err != nil { return err } @@ -241,7 +238,10 @@ func (inst *instance) startFuchsiaLogs() error { // `ffx log` outputs some buffered logs by default, and logs from early boot // trigger a false positive from the unexpected reboot check. To avoid this, // only request logs from now on. - cmd := inst.ffxCommand("--target", inst.name, "log", "--since", "now", + cmd := inst.ffxCommand( + true, + "--target", inst.name, + "log", "--since", "now", "--show-metadata", "--show-full-moniker", "--no-color", "--exclude-tags", "netlink") cmd.Stdout = inst.wpipe @@ -259,6 +259,7 @@ func (inst *instance) startFuchsiaLogs() error { func (inst *instance) startSshdAndConnect() error { if _, err := inst.runFfx( 5*time.Minute, + true, "--target", inst.name, "component", @@ -273,6 +274,7 @@ func (inst *instance) startSshdAndConnect() error { } if _, err := inst.runFfx( 5*time.Minute, + true, "--target", inst.name, "component", @@ -287,6 +289,7 @@ func (inst *instance) startSshdAndConnect() error { } if _, err := inst.runFfx( 5*time.Minute, + true, "--target", inst.name, "component", @@ -308,6 +311,7 @@ func (inst *instance) connect() error { } address, err := inst.runFfx( 30*time.Second, + true, "--target", inst.name, "target", @@ -324,7 +328,8 @@ func (inst *instance) connect() error { "-o", "UserKnownHostsFile=/dev/null", "-i", inst.sshPrivKey, "-NT", - "-L", fmt.Sprintf("localhost:%d:localhost:7000", inst.port), fmt.Sprintf("ssh://%s", bytes.Trim(address, "\n")), + "-L", fmt.Sprintf("localhost:%d:localhost:7000", inst.port), + fmt.Sprintf("ssh://%s", bytes.Trim(address, "\n")), ) cmd.Stderr = os.Stderr if err = cmd.Start(); err != nil { @@ -340,18 +345,30 @@ func (inst *instance) connect() error { return nil } -func (inst *instance) ffxCommand(args ...string) *exec.Cmd { +func (inst *instance) ffxCommand(isolated bool, args ...string) *exec.Cmd { + config := []string{"-c", "log.enabled=false,ffx.analytics.disabled=true"} + if !isolated { + config = append(config, "-c", "daemon.autostart=false") + } + args = slices.Concat(config, args) cmd := osutil.Command(inst.ffxBinary, args...) cmd.Dir = inst.fuchsiaDir - cmd.Env = append(cmd.Environ(), "FFX_ISOLATE_DIR="+inst.ffxDir, "FUCHSIA_ANALYTICS_DISABLED=1") + cmd.Env = append(cmd.Environ(), "FUCHSIA_ANALYTICS_DISABLED=1") + if isolated { + cmd.Env = append(cmd.Env, "FFX_ISOLATE_DIR="+inst.ffxDir) + } return cmd } -func (inst *instance) runFfx(timeout time.Duration, args ...string) ([]byte, error) { +func (inst *instance) runFfx(timeout time.Duration, isolated bool, args ...string) ([]byte, error) { if inst.debug { - log.Logf(1, "instance %s: running ffx: %q", inst.name, args) + isolation := "without" + if isolated { + isolation = "with" + } + log.Logf(1, "instance %s: running ffx %s isolation: %q", inst.name, isolation, args) } - cmd := inst.ffxCommand(args...) + cmd := inst.ffxCommand(isolated, args...) cmd.Stderr = os.Stderr output, err := osutil.Run(timeout, cmd) if inst.debug { @@ -360,6 +377,36 @@ func (inst *instance) runFfx(timeout time.Duration, args ...string) ([]byte, err return output, err } +// Gets a value from ffx's default configuration. +func (inst *instance) getFfxConfigValue(key string) (string, error) { + rawValue, err := inst.runFfx( + 30*time.Second, + false, + "config", "get", key) + if err != nil { + return "", err + } + return string(bytes.Trim(rawValue, "\"\n")), nil +} + +// Copies values from ffx's default configuration into the ffx isolate's configuration. +func (inst *instance) copyFfxConfigValuesToIsolate(keys ...string) error { + for _, key := range keys { + value, err := inst.getFfxConfigValue(key) + if err != nil { + return err + } + _, err = inst.runFfx( + 30*time.Second, + true, + "config", "set", key, value) + if err != nil { + return err + } + } + return nil +} + // Runs a command inside the fuchsia directory. func (inst *instance) runCommand(cmd string, args ...string) error { if inst.debug { -- cgit mrf-deployment