aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2022-03-31 18:26:42 +0000
committerAleksandr Nogikh <wp32pw@gmail.com>2022-04-29 17:16:33 +0200
commita04ae3093de7eebc147770fe38a5bda96b5c0634 (patch)
tree5d7062a73b354b5f1906847835e1c00804a572a5
parent7f2625f8905f7d981475fa314c3d06c56c7bd4b0 (diff)
all: use the same prog execution code throughout the project
Previously it was copypasted in pkg/instance, pkg/repro, tools/syz-crash. Use the single implementation instead. Also, this commit fixes a bug - the previous code always set collide to true while reproducing a bug, which led to an immediate syz-exexprog's exit. As a result, newer bugs with .syz repro only were never actually reproduced on #syz test requests.
-rw-r--r--pkg/instance/execprog.go159
-rw-r--r--pkg/instance/instance.go86
-rw-r--r--pkg/repro/repro.go177
-rw-r--r--tools/syz-crush/crush.go72
4 files changed, 256 insertions, 238 deletions
diff --git a/pkg/instance/execprog.go b/pkg/instance/execprog.go
new file mode 100644
index 000000000..7610298a6
--- /dev/null
+++ b/pkg/instance/execprog.go
@@ -0,0 +1,159 @@
+// 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.
+
+package instance
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "github.com/google/syzkaller/pkg/csource"
+ "github.com/google/syzkaller/pkg/mgrconfig"
+ "github.com/google/syzkaller/pkg/osutil"
+ "github.com/google/syzkaller/pkg/report"
+ "github.com/google/syzkaller/prog"
+ "github.com/google/syzkaller/vm"
+)
+
+type ExecutorLogger func(int, string, ...interface{})
+
+type OptionalConfig struct {
+ ExitCondition vm.ExitCondition
+ Logf ExecutorLogger
+ OldFlagsCompatMode bool
+}
+
+type ExecProgInstance struct {
+ execprogBin string
+ executorBin string
+ reporter *report.Reporter
+ mgrCfg *mgrconfig.Config
+ VMInstance *vm.Instance
+ OptionalConfig
+}
+
+type RunResult struct {
+ Report *report.Report
+}
+
+func SetupExecProg(vmInst *vm.Instance, mgrCfg *mgrconfig.Config, reporter *report.Reporter,
+ opt *OptionalConfig) (*ExecProgInstance, error) {
+ execprogBin, err := vmInst.Copy(mgrCfg.ExecprogBin)
+ if err != nil {
+ vmInst.Close()
+ return nil, &TestError{Title: fmt.Sprintf("failed to copy syz-execprog to VM: %v", err)}
+ }
+ executorBin := mgrCfg.SysTarget.ExecutorBin
+ if executorBin == "" {
+ executorBin, err = vmInst.Copy(mgrCfg.ExecutorBin)
+ if err != nil {
+ vmInst.Close()
+ return nil, &TestError{Title: fmt.Sprintf("failed to copy syz-executor to VM: %v", err)}
+ }
+ }
+ ret := &ExecProgInstance{
+ execprogBin: execprogBin,
+ executorBin: executorBin,
+ reporter: reporter,
+ mgrCfg: mgrCfg,
+ VMInstance: vmInst,
+ }
+ if opt != nil {
+ ret.OptionalConfig = *opt
+ }
+ if ret.Logf == nil {
+ ret.Logf = func(int, string, ...interface{}) {}
+ }
+ if ret.ExitCondition == 0 {
+ ret.ExitCondition = vm.ExitTimeout | vm.ExitNormal | vm.ExitError
+ }
+ return ret, nil
+}
+
+func CreateExecProgInstance(vmPool *vm.Pool, vmIndex int, mgrCfg *mgrconfig.Config,
+ reporter *report.Reporter, opt *OptionalConfig) (*ExecProgInstance, error) {
+ vmInst, err := vmPool.Create(vmIndex)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create VM: %v", err)
+ }
+ ret, err := SetupExecProg(vmInst, mgrCfg, reporter, opt)
+ if err != nil {
+ vmInst.Close()
+ return nil, err
+ }
+ return ret, nil
+}
+
+func (inst *ExecProgInstance) runCommand(command string, duration time.Duration) (*RunResult, error) {
+ outc, errc, err := inst.VMInstance.Run(duration, nil, command)
+ if err != nil {
+ return nil, fmt.Errorf("failed to run command in VM: %v", err)
+ }
+ result := &RunResult{}
+ result.Report = inst.VMInstance.MonitorExecution(outc, errc, inst.reporter, inst.ExitCondition)
+ if result.Report == nil {
+ inst.Logf(2, "program did not crash")
+ } else {
+ if err := inst.reporter.Symbolize(result.Report); err != nil {
+ return nil, fmt.Errorf("failed to symbolize report: %v", err)
+ }
+ inst.Logf(2, "program crashed: %v", result.Report.Title)
+ }
+ return result, nil
+}
+
+func (inst *ExecProgInstance) runBinary(bin string, duration time.Duration) (*RunResult, error) {
+ bin, err := inst.VMInstance.Copy(bin)
+ if err != nil {
+ return nil, &TestError{Title: fmt.Sprintf("failed to copy binary to VM: %v", err)}
+ }
+ return inst.runCommand(bin, duration)
+}
+
+func (inst *ExecProgInstance) RunCProg(p *prog.Prog, duration time.Duration,
+ opts csource.Options) (*RunResult, error) {
+ src, err := csource.Write(p, opts)
+ if err != nil {
+ return nil, err
+ }
+ inst.Logf(2, "testing compiled C program (duration=%v, %+v): %s", duration, opts, p)
+ return inst.RunCProgRaw(src, p.Target, duration)
+}
+
+func (inst *ExecProgInstance) RunCProgRaw(src []byte, target *prog.Target,
+ duration time.Duration) (*RunResult, error) {
+ bin, err := csource.BuildNoWarn(target, src)
+ if err != nil {
+ return nil, err
+ }
+ defer os.Remove(bin)
+ return inst.runBinary(bin, duration)
+}
+
+func (inst *ExecProgInstance) RunSyzProgFile(progFile string, duration time.Duration,
+ opts csource.Options) (*RunResult, error) {
+ vmProgFile, err := inst.VMInstance.Copy(progFile)
+ if err != nil {
+ return nil, &TestError{Title: fmt.Sprintf("failed to copy prog to VM: %v", err)}
+ }
+ target := inst.mgrCfg.SysTarget
+ faultCall := -1
+ if opts.Fault {
+ faultCall = opts.FaultCall
+ }
+ command := ExecprogCmd(inst.execprogBin, inst.executorBin, target.OS, target.Arch, opts.Sandbox,
+ opts.Repeat, opts.Threaded, opts.Collide, opts.Procs, faultCall, opts.FaultNth,
+ !inst.OldFlagsCompatMode, inst.mgrCfg.Timeouts.Slowdown, vmProgFile)
+ return inst.runCommand(command, duration)
+}
+
+func (inst *ExecProgInstance) RunSyzProg(syzProg []byte, duration time.Duration,
+ opts csource.Options) (*RunResult, error) {
+ progFile, err := osutil.WriteTempFile(syzProg)
+ if err != nil {
+ return nil, err
+ }
+ defer os.Remove(progFile)
+ return inst.RunSyzProgFile(progFile, duration, opts)
+}
diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go
index a3a87d338..218408191 100644
--- a/pkg/instance/instance.go
+++ b/pkg/instance/instance.go
@@ -360,30 +360,22 @@ func (inst *inst) testInstance() error {
}
func (inst *inst) testRepro() error {
- cfg := inst.cfg
- if len(inst.reproSyz) > 0 {
- execprogBin, err := inst.vm.Copy(cfg.ExecprogBin)
- if err != nil {
- return &TestError{Title: fmt.Sprintf("failed to copy test binary to VM: %v", err)}
- }
- // If ExecutorBin is provided, it means that syz-executor is already in the image,
- // so no need to copy it.
- executorBin := cfg.SysTarget.ExecutorBin
- if executorBin == "" {
- executorBin, err = inst.vm.Copy(inst.cfg.ExecutorBin)
- if err != nil {
- return &TestError{Title: fmt.Sprintf("failed to copy test binary to VM: %v", err)}
- }
- }
- progFile := filepath.Join(cfg.Workdir, "repro.prog")
- if err := osutil.WriteFile(progFile, inst.reproSyz); err != nil {
- return fmt.Errorf("failed to write temp file: %v", err)
- }
- vmProgFile, err := inst.vm.Copy(progFile)
- if err != nil {
- return &TestError{Title: fmt.Sprintf("failed to copy test binary to VM: %v", err)}
+ var err error
+ execProg, err := SetupExecProg(inst.vm, inst.cfg, inst.reporter, &OptionalConfig{
+ OldFlagsCompatMode: !inst.optionalFlags,
+ })
+ if err != nil {
+ return err
+ }
+ transformError := func(res *RunResult, err error) error {
+ if err != nil && res.Report != nil {
+ return &CrashError{Report: res.Report}
}
- opts, err := csource.DeserializeOptions(inst.reproOpts)
+ return err
+ }
+ if len(inst.reproSyz) > 0 {
+ var opts csource.Options
+ opts, err = csource.DeserializeOptions(inst.reproOpts)
if err != nil {
return err
}
@@ -394,47 +386,17 @@ func (inst *inst) testRepro() error {
if opts.Sandbox == "" {
opts.Sandbox = "none"
}
- if !opts.Fault {
- opts.FaultCall = -1
- }
- cmdSyz := ExecprogCmd(execprogBin, executorBin, cfg.TargetOS, cfg.TargetArch, opts.Sandbox,
- true, true, opts.Collide, cfg.Procs, opts.FaultCall, opts.FaultNth, inst.optionalFlags,
- cfg.Timeouts.Slowdown, vmProgFile)
- if err := inst.testProgram(cmdSyz, cfg.Timeouts.NoOutputRunningTime); err != nil {
- return err
- }
- }
- if len(inst.reproC) == 0 {
- return nil
- }
- bin, err := csource.BuildNoWarn(cfg.Target, inst.reproC)
- if err != nil {
- return err
- }
- defer os.Remove(bin)
- vmBin, err := inst.vm.Copy(bin)
- if err != nil {
- return &TestError{Title: fmt.Sprintf("failed to copy test binary to VM: %v", err)}
- }
- // We should test for more than full "no output" timeout, but the problem is that C reproducers
- // don't print anything, so we will get a false "no output" crash.
- return inst.testProgram(vmBin, cfg.Timeouts.NoOutput/2)
-}
-
-func (inst *inst) testProgram(command string, testTime time.Duration) error {
- outc, errc, err := inst.vm.Run(testTime, nil, command)
- if err != nil {
- return fmt.Errorf("failed to run binary in VM: %v", err)
- }
- rep := inst.vm.MonitorExecution(outc, errc, inst.reporter,
- vm.ExitTimeout|vm.ExitNormal|vm.ExitError)
- if rep == nil {
- return nil
+ opts.Repeat, opts.Threaded = true, true
+ err = transformError(execProg.RunSyzProg(inst.reproSyz,
+ inst.cfg.Timeouts.NoOutputRunningTime, opts))
}
- if err := inst.reporter.Symbolize(rep); err != nil {
- log.Logf(0, "failed to symbolize report: %v", err)
+ if err == nil && len(inst.reproC) > 0 {
+ // We should test for more than full "no output" timeout, but the problem is that C reproducers
+ // don't print anything, so we will get a false "no output" crash.
+ err = transformError(execProg.RunCProgRaw(inst.reproC, inst.cfg.Target,
+ inst.cfg.Timeouts.NoOutput/2))
}
- return &CrashError{Report: rep}
+ return err
}
type OptionalFuzzerArgs struct {
diff --git a/pkg/repro/repro.go b/pkg/repro/repro.go
index 8726cbfd3..fe20c7330 100644
--- a/pkg/repro/repro.go
+++ b/pkg/repro/repro.go
@@ -6,17 +6,15 @@ package repro
import (
"bytes"
"fmt"
- "os"
"sort"
"sync"
"time"
"github.com/google/syzkaller/pkg/csource"
"github.com/google/syzkaller/pkg/host"
- instancePkg "github.com/google/syzkaller/pkg/instance"
+ "github.com/google/syzkaller/pkg/instance"
"github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/mgrconfig"
- "github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report"
"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
@@ -42,12 +40,17 @@ type Stats struct {
SimplifyCTime time.Duration
}
+type reproInstance struct {
+ index int
+ execProg *instance.ExecProgInstance
+}
+
type context struct {
target *targets.Target
reporter *report.Reporter
crashTitle string
crashType report.Type
- instances chan *instance
+ instances chan *reproInstance
bootRequests chan int
testTimeouts []time.Duration
startOpts csource.Options
@@ -56,13 +59,6 @@ type context struct {
timeouts targets.Timeouts
}
-type instance struct {
- *vm.Instance
- index int
- execprogBin string
- executorBin string
-}
-
func Run(crashLog []byte, cfg *mgrconfig.Config, features *host.Features, reporter *report.Reporter,
vmPool *vm.Pool, vmIndexes []int) (*Result, *Stats, error) {
if len(vmIndexes) == 0 {
@@ -103,7 +99,7 @@ func Run(crashLog []byte, cfg *mgrconfig.Config, features *host.Features, report
reporter: reporter,
crashTitle: crashTitle,
crashType: crashType,
- instances: make(chan *instance, len(vmIndexes)),
+ instances: make(chan *reproInstance, len(vmIndexes)),
bootRequests: make(chan int, len(vmIndexes)),
testTimeouts: testTimeouts,
startOpts: createStartOptions(cfg, features, crashType),
@@ -118,7 +114,7 @@ func Run(crashLog []byte, cfg *mgrconfig.Config, features *host.Features, report
go func() {
defer wg.Done()
for vmIndex := range ctx.bootRequests {
- var inst *instance
+ var inst *instance.ExecProgInstance
maxTry := 3
for try := 0; try < maxTry; try++ {
select {
@@ -128,7 +124,8 @@ func Run(crashLog []byte, cfg *mgrconfig.Config, features *host.Features, report
default:
}
var err error
- inst, err = ctx.initInstance(cfg, vmPool, vmIndex)
+ inst, err = instance.CreateExecProgInstance(vmPool, vmIndex, cfg,
+ reporter, &instance.OptionalConfig{Logf: ctx.reproLogf})
if err != nil {
ctx.reproLogf(0, "failed to init instance: %v", err)
time.Sleep(10 * time.Second)
@@ -139,7 +136,7 @@ func Run(crashLog []byte, cfg *mgrconfig.Config, features *host.Features, report
if inst == nil {
break
}
- ctx.instances <- inst
+ ctx.instances <- &reproInstance{execProg: inst, index: vmIndex}
}
}()
}
@@ -150,7 +147,7 @@ func Run(crashLog []byte, cfg *mgrconfig.Config, features *host.Features, report
defer func() {
close(ctx.bootRequests)
for inst := range ctx.instances {
- inst.Close()
+ inst.execProg.VMInstance.Close()
}
}()
@@ -211,32 +208,6 @@ func createStartOptions(cfg *mgrconfig.Config, features *host.Features, crashTyp
return opts
}
-func (ctx *context) initInstance(cfg *mgrconfig.Config, vmPool *vm.Pool, vmIndex int) (*instance, error) {
- vmInst, err := vmPool.Create(vmIndex)
- if err != nil {
- return nil, fmt.Errorf("failed to create VM: %v", err)
- }
- execprogBin, err := vmInst.Copy(cfg.ExecprogBin)
- if err != nil {
- vmInst.Close()
- return nil, fmt.Errorf("failed to copy to VM: %v", err)
- }
- executorBin := ctx.target.ExecutorBin
- if executorBin == "" {
- executorBin, err = vmInst.Copy(cfg.ExecutorBin)
- if err != nil {
- vmInst.Close()
- return nil, fmt.Errorf("failed to copy to VM: %v", err)
- }
- }
- return &instance{
- Instance: vmInst,
- index: vmIndex,
- execprogBin: execprogBin,
- executorBin: executorBin,
- }, nil
-}
-
func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, error) {
// Cut programs that were executed after crash.
for i, ent := range entries {
@@ -546,28 +517,47 @@ func (ctx *context) testProg(p *prog.Prog, duration time.Duration, opts csource.
return ctx.testProgs([]*prog.LogEntry{&entry}, duration, opts)
}
-func (ctx *context) testProgs(entries []*prog.LogEntry, duration time.Duration, opts csource.Options) (
- crashed bool, err error) {
+func (ctx *context) testWithInstance(callback func(inst *instance.ExecProgInstance) (rep *instance.RunResult,
+ err error)) (bool, error) {
inst := <-ctx.instances
if inst == nil {
return false, fmt.Errorf("all VMs failed to boot")
}
defer ctx.returnInstance(inst)
- if len(entries) == 0 {
- return false, fmt.Errorf("no programs to execute")
- }
-
- pstr := encodeEntries(entries)
- progFile, err := osutil.WriteTempFile(pstr)
+ result, err := callback(inst.execProg)
if err != nil {
return false, err
}
- defer os.Remove(progFile)
- vmProgFile, err := inst.Copy(progFile)
- if err != nil {
- return false, fmt.Errorf("failed to copy to VM: %v", err)
+ rep := result.Report
+ if rep == nil {
+ return false, nil
+ }
+ if rep.Suppressed {
+ ctx.reproLogf(2, "suppressed program crash: %v", rep.Title)
+ return false, nil
+ }
+ if ctx.crashType == report.MemoryLeak && rep.Type != report.MemoryLeak {
+ ctx.reproLogf(2, "not a leak crash: %v", rep.Title)
+ return false, nil
+ }
+ ctx.report = rep
+ return true, nil
+}
+
+func encodeEntries(entries []*prog.LogEntry) []byte {
+ buf := new(bytes.Buffer)
+ for _, ent := range entries {
+ fmt.Fprintf(buf, "executing program %v:\n%v", ent.Proc, string(ent.P.Serialize()))
}
+ return buf.Bytes()
+}
+func (ctx *context) testProgs(entries []*prog.LogEntry, duration time.Duration, opts csource.Options) (
+ crashed bool, err error) {
+ if len(entries) == 0 {
+ return false, fmt.Errorf("no programs to execute")
+ }
+ pstr := encodeEntries(entries)
program := entries[0].P.String()
if len(entries) > 1 {
program = "["
@@ -579,77 +569,22 @@ func (ctx *context) testProgs(entries []*prog.LogEntry, duration time.Duration,
}
program += "]"
}
-
- command := instancePkg.ExecprogCmd(inst.execprogBin, inst.executorBin,
- ctx.target.OS, ctx.target.Arch, opts.Sandbox, opts.Repeat,
- opts.Threaded, opts.Collide, opts.Procs, -1, -1, true, ctx.timeouts.Slowdown, vmProgFile)
ctx.reproLogf(2, "testing program (duration=%v, %+v): %s", duration, opts, program)
ctx.reproLogf(3, "detailed listing:\n%s", pstr)
- return ctx.testImpl(inst.Instance, command, duration)
+ return ctx.testWithInstance(func(inst *instance.ExecProgInstance) (*instance.RunResult, error) {
+ return inst.RunSyzProg(pstr, duration, opts)
+ })
}
func (ctx *context) testCProg(p *prog.Prog, duration time.Duration, opts csource.Options) (crashed bool, err error) {
- src, err := csource.Write(p, opts)
- if err != nil {
- return false, err
- }
- bin, err := csource.BuildNoWarn(p.Target, src)
- if err != nil {
- return false, err
- }
- defer os.Remove(bin)
- ctx.reproLogf(2, "testing compiled C program (duration=%v, %+v): %s", duration, opts, p)
- crashed, err = ctx.testBin(bin, duration)
- if err != nil {
- return false, err
- }
- return crashed, nil
-}
-
-func (ctx *context) testBin(bin string, duration time.Duration) (crashed bool, err error) {
- inst := <-ctx.instances
- if inst == nil {
- return false, fmt.Errorf("all VMs failed to boot")
- }
- defer ctx.returnInstance(inst)
-
- bin, err = inst.Copy(bin)
- if err != nil {
- return false, fmt.Errorf("failed to copy to VM: %v", err)
- }
- return ctx.testImpl(inst.Instance, bin, duration)
-}
-
-func (ctx *context) testImpl(inst *vm.Instance, command string, duration time.Duration) (crashed bool, err error) {
- outc, errc, err := inst.Run(duration, nil, command)
- if err != nil {
- return false, fmt.Errorf("failed to run command in VM: %v", err)
- }
- rep := inst.MonitorExecution(outc, errc, ctx.reporter,
- vm.ExitTimeout|vm.ExitNormal|vm.ExitError)
- if rep == nil {
- ctx.reproLogf(2, "program did not crash")
- return false, nil
- }
- if err := ctx.reporter.Symbolize(rep); err != nil {
- return false, fmt.Errorf("failed to symbolize report: %v", err)
- }
- if rep.Suppressed {
- ctx.reproLogf(2, "suppressed program crash: %v", rep.Title)
- return false, nil
- }
- if ctx.crashType == report.MemoryLeak && rep.Type != report.MemoryLeak {
- ctx.reproLogf(2, "not a leak crash: %v", rep.Title)
- return false, nil
- }
- ctx.report = rep
- ctx.reproLogf(2, "program crashed: %v", rep.Title)
- return true, nil
+ return ctx.testWithInstance(func(inst *instance.ExecProgInstance) (*instance.RunResult, error) {
+ return inst.RunCProg(p, duration, opts)
+ })
}
-func (ctx *context) returnInstance(inst *instance) {
+func (ctx *context) returnInstance(inst *reproInstance) {
ctx.bootRequests <- inst.index
- inst.Close()
+ inst.execProg.VMInstance.Close()
}
func (ctx *context) reproLogf(level int, format string, args ...interface{}) {
@@ -775,14 +710,6 @@ func chunksToStr(chunks [][]*prog.LogEntry) string {
return log
}
-func encodeEntries(entries []*prog.LogEntry) []byte {
- buf := new(bytes.Buffer)
- for _, ent := range entries {
- fmt.Fprintf(buf, "executing program %v:\n%v", ent.Proc, string(ent.P.Serialize()))
- }
- return buf.Bytes()
-}
-
type Simplify func(opts *csource.Options) bool
var progSimplifies = []Simplify{
diff --git a/tools/syz-crush/crush.go b/tools/syz-crush/crush.go
index 1c571a153..ac077befd 100644
--- a/tools/syz-crush/crush.go
+++ b/tools/syz-crush/crush.go
@@ -78,23 +78,10 @@ func main() {
runType := LogFile
if strings.HasSuffix(reproduceMe, ".c") {
runType = CProg
- }
- if runType == CProg {
- execprog, err := ioutil.ReadFile(reproduceMe)
- if err != nil {
- log.Fatalf("error reading source file from '%s'", reproduceMe)
- }
-
- cfg.ExecprogBin, err = csource.BuildNoWarn(cfg.Target, execprog)
- if err != nil {
- log.Fatalf("failed to build source file: %v", err)
- }
-
- log.Printf("compiled csource %v to cprog: %v", reproduceMe, cfg.ExecprogBin)
+ log.Printf("reproducing from C source file: %v", reproduceMe)
} else {
log.Printf("reproducing from log file: %v", reproduceMe)
}
-
log.Printf("booting %v test machines...", vmPool.Count())
runDone := make(chan *report.Report)
var shutdown, stoppedWorkers uint32
@@ -169,54 +156,37 @@ func storeCrash(cfg *mgrconfig.Config, rep *report.Report) {
func runInstance(cfg *mgrconfig.Config, reporter *report.Reporter,
vmPool *vm.Pool, index int, timeout time.Duration, runType FileType) *report.Report {
log.Printf("vm-%v: starting", index)
- inst, err := vmPool.Create(index)
- if err != nil {
- log.Printf("failed to create instance: %v", err)
- return nil
+ optArgs := &instance.OptionalConfig{
+ ExitCondition: vm.ExitTimeout,
}
- defer inst.Close()
-
- execprogBin, err := inst.Copy(cfg.ExecprogBin)
+ var err error
+ inst, err := instance.CreateExecProgInstance(vmPool, index, cfg, reporter, optArgs)
if err != nil {
- log.Printf("failed to copy execprog: %v", err)
+ log.Printf("failed to set up instance: %v", err)
return nil
}
-
- cmd := ""
+ defer inst.VMInstance.Close()
+ file := flag.Args()[0]
+ var res *instance.RunResult
if runType == LogFile {
- // If SyzExecutorCmd is provided, it means that syz-executor is already in
- // the image, so no need to copy it.
- executorBin := cfg.SysTarget.ExecutorBin
- if executorBin == "" {
- executorBin, err = inst.Copy(cfg.ExecutorBin)
- if err != nil {
- log.Printf("failed to copy executor: %v", err)
- return nil
- }
- }
- logFile, err := inst.Copy(flag.Args()[0])
+ opts := csource.DefaultOpts(cfg)
+ opts.Repeat, opts.Threaded = true, true
+ res, err = inst.RunSyzProgFile(file, timeout, opts)
+ } else {
+ var src []byte
+ src, err = ioutil.ReadFile(file)
if err != nil {
- log.Printf("failed to copy log: %v", err)
- return nil
+ log.Fatalf("error reading source file from '%s'", file)
}
-
- cmd = instance.ExecprogCmd(execprogBin, executorBin, cfg.TargetOS, cfg.TargetArch, cfg.Sandbox,
- true, true, true, cfg.Procs, -1, -1, true, cfg.Timeouts.Slowdown, logFile)
- } else {
- cmd = execprogBin
+ res, err = inst.RunCProgRaw(src, cfg.Target, timeout)
}
-
- outc, errc, err := inst.Run(timeout, nil, cmd)
if err != nil {
- log.Printf("failed to run execprog: %v", err)
+ log.Printf("failed to execute program: %v", err)
return nil
}
-
- log.Printf("vm-%v: crushing...", index)
- rep := inst.MonitorExecution(outc, errc, reporter, vm.ExitTimeout)
- if rep != nil {
- log.Printf("vm-%v: crash: %v", index, rep.Title)
- return rep
+ if res.Report != nil {
+ log.Printf("vm-%v: crash: %v", index, res.Report.Title)
+ return res.Report
}
log.Printf("vm-%v: running long enough, stopping", index)
return nil