mirror of
https://github.com/reactos/syzkaller.git
synced 2025-02-26 14:45:32 +00:00

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.
125 lines
3.0 KiB
Go
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)
|
|
}
|
|
}
|