Dmitry Vyukov 04bd6c3d9e pkg/instance: pass -os to execprog/fuzzer only for akaros
Only akaros needs OS, because the rest assume host OS.
But speciying OS for all OSes breaks patch testing on syzbot
because old execprog does not have os flag.
2018-07-06 14:43:24 +02:00

125 lines
3.0 KiB
Go

// Copyright 2016 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.
// syz-crush replays crash log on multiple VMs. Usage:
// syz-crush -config=config.file execution.log
// Intended for reproduction of particularly elusive crashes.
package main
import (
"flag"
"io/ioutil"
"sync"
"sync/atomic"
"time"
"github.com/google/syzkaller/pkg/instance"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/syz-manager/mgrconfig"
"github.com/google/syzkaller/vm"
)
var (
flagConfig = flag.String("config", "", "configuration file")
)
func main() {
flag.Parse()
cfg, err := mgrconfig.LoadFile(*flagConfig)
if err != nil {
log.Fatalf("%v", err)
}
if len(flag.Args()) != 1 {
log.Fatalf("usage: syz-crush -config=config.file execution.log")
}
if _, err := prog.GetTarget(cfg.TargetOS, cfg.TargetArch); err != nil {
log.Fatalf("%v", err)
}
vmPool, err := vm.Create(cfg, false)
if err != nil {
log.Fatalf("%v", err)
}
reporter, err := report.NewReporter(cfg)
if err != nil {
log.Fatalf("%v", err)
}
log.Logf(0, "booting test machines...")
var shutdown uint32
var wg sync.WaitGroup
wg.Add(vmPool.Count() + 1)
for i := 0; i < vmPool.Count(); i++ {
i := i
go func() {
defer wg.Done()
for {
runInstance(cfg, reporter, vmPool, i)
if atomic.LoadUint32(&shutdown) != 0 {
break
}
}
}()
}
shutdownC := make(chan struct{})
osutil.HandleInterrupts(shutdownC)
go func() {
<-shutdownC
wg.Done()
atomic.StoreUint32(&shutdown, 1)
}()
wg.Wait()
}
func runInstance(cfg *mgrconfig.Config, reporter report.Reporter, vmPool *vm.Pool, index int) {
inst, err := vmPool.Create(index)
if err != nil {
log.Logf(0, "failed to create instance: %v", err)
return
}
defer inst.Close()
execprogBin, err := inst.Copy(cfg.SyzExecprogBin)
if err != nil {
log.Logf(0, "failed to copy execprog: %v", err)
return
}
executorBin, err := inst.Copy(cfg.SyzExecutorBin)
if err != nil {
log.Logf(0, "failed to copy executor: %v", err)
return
}
logFile, err := inst.Copy(flag.Args()[0])
if err != nil {
log.Logf(0, "failed to copy log: %v", err)
return
}
cmd := instance.ExecprogCmd(execprogBin, executorBin, cfg.TargetOS, cfg.TargetArch, cfg.Sandbox,
true, true, true, cfg.Procs, -1, -1, logFile)
outc, errc, err := inst.Run(time.Hour, nil, cmd)
if err != nil {
log.Logf(0, "failed to run execprog: %v", err)
return
}
log.Logf(0, "vm-%v: crushing...", index)
rep := inst.MonitorExecution(outc, errc, reporter, false)
if rep == nil {
// This is the only "OK" outcome.
log.Logf(0, "vm-%v: running long enough, restarting", index)
} else {
f, err := ioutil.TempFile(".", "syz-crush")
if err != nil {
log.Logf(0, "failed to create temp file: %v", err)
return
}
defer f.Close()
log.Logf(0, "vm-%v: crashed: %v, saving to %v", index, rep.Title, f.Name())
f.Write(rep.Output)
}
}