aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/instance/instance.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-11-25 09:17:50 +0100
committerDmitry Vyukov <dvyukov@google.com>2020-12-28 14:22:41 +0100
commitcbd0445ec3b0b184db66966d8a47e6b37d13692e (patch)
tree14ed47723c325ef1b388e4e732a70c0fed4fa101 /pkg/instance/instance.go
parent2242f77fdc5a6c50bd8fa1021d2abc8b83e09e8d (diff)
all: make timeouts configurable
Add sys/targets.Timeouts struct that parametrizes timeouts throughout the system. The struct allows to control syscall/program/no output timeouts for OS/arch/VM/etc. See comment on the struct for more details.
Diffstat (limited to 'pkg/instance/instance.go')
-rw-r--r--pkg/instance/instance.go97
1 files changed, 63 insertions, 34 deletions
diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go
index 861d51e72..52881b353 100644
--- a/pkg/instance/instance.go
+++ b/pkg/instance/instance.go
@@ -21,6 +21,7 @@ import (
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report"
+ "github.com/google/syzkaller/pkg/tool"
"github.com/google/syzkaller/pkg/vcs"
"github.com/google/syzkaller/sys/targets"
"github.com/google/syzkaller/vm"
@@ -33,7 +34,8 @@ type Env interface {
}
type env struct {
- cfg *mgrconfig.Config
+ cfg *mgrconfig.Config
+ optionalFlags bool
}
func NewEnv(cfg *mgrconfig.Config) (Env, error) {
@@ -53,20 +55,30 @@ func NewEnv(cfg *mgrconfig.Config) (Env, error) {
return nil, fmt.Errorf("failed to create tmp dir: %v", err)
}
env := &env{
- cfg: cfg,
+ cfg: cfg,
+ optionalFlags: true,
}
return env, nil
}
-func (env *env) BuildSyzkaller(repo, commit string) error {
+func (env *env) BuildSyzkaller(repoURL, commit string) error {
cfg := env.cfg
srcIndex := strings.LastIndex(cfg.Syzkaller, "/src/")
if srcIndex == -1 {
return fmt.Errorf("syzkaller path %q is not in GOPATH", cfg.Syzkaller)
}
- if _, err := vcs.NewSyzkallerRepo(cfg.Syzkaller).CheckoutCommit(repo, commit); err != nil {
+ repo := vcs.NewSyzkallerRepo(cfg.Syzkaller)
+ if _, err := repo.CheckoutCommit(repoURL, commit); err != nil {
return fmt.Errorf("failed to checkout syzkaller repo: %v", err)
}
+ // The following commit ("syz-fuzzer: support optional flags") adds support for optional flags
+ // in syz-fuzzer and syz-execprog. This is required to invoke older binaries with newer flags
+ // without failing due to unknown flags.
+ optionalFlags, err := repo.Contains("64435345f0891706a7e0c7885f5f7487581e6005")
+ if err != nil {
+ return fmt.Errorf("optional flags check failed: %v", err)
+ }
+ env.optionalFlags = optionalFlags
cmd := osutil.Command(MakeBin, "target")
cmd.Dir = cfg.Syzkaller
cmd.Env = append([]string{}, os.Environ()...)
@@ -210,13 +222,14 @@ func (env *env) Test(numVMs int, reproSyz, reproOpts, reproC []byte) ([]error, e
res := make(chan error, numVMs)
for i := 0; i < numVMs; i++ {
inst := &inst{
- cfg: env.cfg,
- reporter: reporter,
- vmPool: vmPool,
- vmIndex: i,
- reproSyz: reproSyz,
- reproOpts: reproOpts,
- reproC: reproC,
+ cfg: env.cfg,
+ optionalFlags: env.optionalFlags,
+ reporter: reporter,
+ vmPool: vmPool,
+ vmIndex: i,
+ reproSyz: reproSyz,
+ reproOpts: reproOpts,
+ reproC: reproC,
}
go func() { res <- inst.test() }()
}
@@ -228,14 +241,15 @@ func (env *env) Test(numVMs int, reproSyz, reproOpts, reproC []byte) ([]error, e
}
type inst struct {
- cfg *mgrconfig.Config
- reporter report.Reporter
- vmPool *vm.Pool
- vm *vm.Instance
- vmIndex int
- reproSyz []byte
- reproOpts []byte
- reproC []byte
+ cfg *mgrconfig.Config
+ optionalFlags bool
+ reporter report.Reporter
+ vmPool *vm.Pool
+ vm *vm.Instance
+ vmIndex int
+ reproSyz []byte
+ reproOpts []byte
+ reproC []byte
}
func (inst *inst) test() error {
@@ -318,8 +332,8 @@ func (inst *inst) testInstance() error {
}
cmd := OldFuzzerCmd(fuzzerBin, executorBin, targets.TestOS, inst.cfg.TargetOS, inst.cfg.TargetArch, fwdAddr,
- inst.cfg.Sandbox, 0, inst.cfg.Cover, true)
- outc, errc, err := inst.vm.Run(10*time.Minute, nil, cmd)
+ inst.cfg.Sandbox, 0, inst.cfg.Cover, true, inst.optionalFlags, inst.cfg.Timeouts.Slowdown)
+ outc, errc, err := inst.vm.Run(10*time.Minute*inst.cfg.Timeouts.Scale, nil, cmd)
if err != nil {
return fmt.Errorf("failed to run binary in VM: %v", err)
}
@@ -381,8 +395,9 @@ func (inst *inst) testRepro() error {
opts.FaultCall = -1
}
cmdSyz := ExecprogCmd(execprogBin, executorBin, cfg.TargetOS, cfg.TargetArch, opts.Sandbox,
- true, true, true, cfg.Procs, opts.FaultCall, opts.FaultNth, vmProgFile)
- if err := inst.testProgram(cmdSyz, 7*time.Minute); err != nil {
+ true, true, true, cfg.Procs, opts.FaultCall, opts.FaultNth, inst.optionalFlags,
+ cfg.Timeouts.Slowdown, vmProgFile)
+ if err := inst.testProgram(cmdSyz, cfg.Timeouts.NoOutputRunningTime); err != nil {
return err
}
}
@@ -398,9 +413,9 @@ func (inst *inst) testRepro() error {
if err != nil {
return &TestError{Title: fmt.Sprintf("failed to copy test binary to VM: %v", err)}
}
- // We should test for longer (e.g. 5 mins), but the problem is that
- // reproducer does not print anything, so after 3 mins we detect "no output".
- return inst.testProgram(vmBin, time.Minute)
+ // 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 {
@@ -420,7 +435,7 @@ func (inst *inst) testProgram(command string, testTime time.Duration) error {
}
func FuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox string, procs, verbosity int,
- cover, debug, test, runtest bool) string {
+ cover, debug, test, runtest, optionalFlags bool, slowdown int) string {
osArg := ""
if targets.Get(OS, arch).HostFuzzer {
// Only these OSes need the flag, because the rest assume host OS.
@@ -436,18 +451,26 @@ func FuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox string, procs,
if verbosity != 0 {
verbosityArg = fmt.Sprintf(" -vv=%v", verbosity)
}
+ optionalArg := ""
+ if optionalFlags {
+ optionalArg = " " + tool.OptionalFlags([]tool.Flag{
+ {Name: "slowdown", Value: fmt.Sprint(slowdown)},
+ })
+ }
return fmt.Sprintf("%v -executor=%v -name=%v -arch=%v%v -manager=%v -sandbox=%v"+
- " -procs=%v -cover=%v -debug=%v -test=%v%v%v",
+ " -procs=%v -cover=%v -debug=%v -test=%v%v%v%v",
fuzzer, executor, name, arch, osArg, fwdAddr, sandbox,
- procs, cover, debug, test, runtestArg, verbosityArg)
+ procs, cover, debug, test, runtestArg, verbosityArg, optionalArg)
}
-func OldFuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox string, procs int, cover, test bool) string {
- return FuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox, procs, 0, cover, false, test, false)
+func OldFuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox string, procs int,
+ cover, test, optionalFlags bool, slowdown int) string {
+ return FuzzerCmd(fuzzer, executor, name, OS, arch, fwdAddr, sandbox, procs, 0, cover, false, test, false,
+ optionalFlags, slowdown)
}
func ExecprogCmd(execprog, executor, OS, arch, sandbox string, repeat, threaded, collide bool,
- procs, faultCall, faultNth int, progFile string) string {
+ procs, faultCall, faultNth int, optionalFlags bool, slowdown int, progFile string) string {
repeatCount := 1
if repeat {
repeatCount = 0
@@ -456,12 +479,18 @@ func ExecprogCmd(execprog, executor, OS, arch, sandbox string, repeat, threaded,
if targets.Get(OS, arch).HostFuzzer {
osArg = " -os=" + OS
}
+ optionalArg := ""
+ if optionalFlags {
+ optionalArg = " " + tool.OptionalFlags([]tool.Flag{
+ {Name: "slowdown", Value: fmt.Sprint(slowdown)},
+ })
+ }
return fmt.Sprintf("%v -executor=%v -arch=%v%v -sandbox=%v"+
" -procs=%v -repeat=%v -threaded=%v -collide=%v -cover=0"+
- " -fault_call=%v -fault_nth=%v %v",
+ " -fault_call=%v -fault_nth=%v%v %v",
execprog, executor, arch, osArg, sandbox,
procs, repeatCount, threaded, collide,
- faultCall, faultNth, progFile)
+ faultCall, faultNth, optionalArg, progFile)
}
var MakeBin = func() string {