From 2a075d57ab619ae5333c823cc260a722ab0c47fe Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 21 Jun 2018 14:38:08 +0200 Subject: pkg/report: allow to specify suppressions per OS Currently all (linux-specific) suppressions are hardcoded in mgrconfig. This is very wrong. Move them to pkg/report and allow to specify per OS. Add gvisor-specific suppressions. This required a bit of refactoring. Introduce mgrconfig.KernelObj finally. Make report.NewReporter and vm.Create accept mgrconfig directly instead of passing it as multiple scattered args. Remove tools/syz-parse and it always did the same as tools/syz-symbolize. Simplify global vars in syz-manager/cover.go. Create reporter eagerly in manager. Use sort.Slice more. Overall -90 lines removed. --- pkg/instance/instance.go | 8 +++----- pkg/report/freebsd.go | 9 ++------- pkg/report/fuchsia.go | 9 ++------- pkg/report/gvisor.go | 13 +++++++----- pkg/report/linux.go | 32 ++++++++++++++++++++--------- pkg/report/linux_test.go | 28 ++++++++++---------------- pkg/report/netbsd.go | 9 ++------- pkg/report/report.go | 51 +++++++++++++++++++++++++++++++---------------- pkg/report/report_test.go | 6 +++++- pkg/report/stub.go | 9 ++------- 10 files changed, 92 insertions(+), 82 deletions(-) (limited to 'pkg') diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go index b5f44376c..e7ab3c9ec 100644 --- a/pkg/instance/instance.go +++ b/pkg/instance/instance.go @@ -82,7 +82,7 @@ func (env *Env) BuildKernel(compilerBin, userspaceDir, cmdlineFile, sysctlFile s if err := kernel.Build(cfg.KernelSrc, compilerBin, kernelConfig); err != nil { return osutil.PrependContext("kernel build failed", err) } - cfg.Vmlinux = filepath.Join(cfg.KernelSrc, "vmlinux") + cfg.KernelObj = cfg.KernelSrc cfg.Image = filepath.Join(cfg.Workdir, "syz-image") cfg.SSHKey = filepath.Join(cfg.Workdir, "syz-key") if err := kernel.CreateImage(cfg.TargetOS, cfg.TargetVMArch, cfg.Type, @@ -118,13 +118,11 @@ func (env *Env) Test(numVMs int, reproSyz, reproOpts, reproC []byte) ([]error, e if err := mgrconfig.Complete(env.cfg); err != nil { return nil, err } - reporter, err := report.NewReporter(env.cfg.TargetOS, env.cfg.Type, - env.cfg.KernelSrc, filepath.Dir(env.cfg.Vmlinux), nil, env.cfg.ParsedIgnores) + reporter, err := report.NewReporter(env.cfg) if err != nil { return nil, err } - vmEnv := mgrconfig.CreateVMEnv(env.cfg, false) - vmPool, err := vm.Create(env.cfg.Type, vmEnv) + vmPool, err := vm.Create(env.cfg, false) if err != nil { return nil, fmt.Errorf("failed to create VM pool: %v", err) } diff --git a/pkg/report/freebsd.go b/pkg/report/freebsd.go index f16f2c15d..6e3bbb7e5 100644 --- a/pkg/report/freebsd.go +++ b/pkg/report/freebsd.go @@ -6,26 +6,21 @@ package report import ( "bytes" "regexp" - - "github.com/google/syzkaller/pkg/symbolizer" ) type freebsd struct { kernelSrc string kernelObj string - symbols map[string][]symbolizer.Symbol ignores []*regexp.Regexp } -func ctorFreebsd(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symbol, - ignores []*regexp.Regexp) (Reporter, error) { +func ctorFreebsd(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) { ctx := &freebsd{ kernelSrc: kernelSrc, kernelObj: kernelObj, - symbols: symbols, ignores: ignores, } - return ctx, nil + return ctx, nil, nil } func (ctx *freebsd) ContainsCrash(output []byte) bool { diff --git a/pkg/report/fuchsia.go b/pkg/report/fuchsia.go index 67a3e2ae9..4e227fc93 100644 --- a/pkg/report/fuchsia.go +++ b/pkg/report/fuchsia.go @@ -6,26 +6,21 @@ package report import ( "bytes" "regexp" - - "github.com/google/syzkaller/pkg/symbolizer" ) type fuchsia struct { kernelSrc string kernelObj string - symbols map[string][]symbolizer.Symbol ignores []*regexp.Regexp } -func ctorFuchsia(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symbol, - ignores []*regexp.Regexp) (Reporter, error) { +func ctorFuchsia(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) { ctx := &fuchsia{ kernelSrc: kernelSrc, kernelObj: kernelObj, - symbols: symbols, ignores: ignores, } - return ctx, nil + return ctx, nil, nil } func (ctx *fuchsia) ContainsCrash(output []byte) bool { diff --git a/pkg/report/gvisor.go b/pkg/report/gvisor.go index 357051fb0..fa1c8476e 100644 --- a/pkg/report/gvisor.go +++ b/pkg/report/gvisor.go @@ -6,20 +6,23 @@ package report import ( "bytes" "regexp" - - "github.com/google/syzkaller/pkg/symbolizer" ) type gvisor struct { ignores []*regexp.Regexp } -func ctorGvisor(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symbol, - ignores []*regexp.Regexp) (Reporter, error) { +func ctorGvisor(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) { ctx := &gvisor{ ignores: ignores, } - return ctx, nil + suppressions := []string{ + "fatal error: runtime: out of memory", + "fatal error: runtime: cannot allocate memory", + "panic: failed to start executor binary", + "panic: executor failed: pthread_create failed", + } + return ctx, suppressions, nil } func (ctx *gvisor) ContainsCrash(output []byte) bool { diff --git a/pkg/report/linux.go b/pkg/report/linux.go index 0fc67f80d..f29235b69 100644 --- a/pkg/report/linux.go +++ b/pkg/report/linux.go @@ -32,17 +32,15 @@ type linux struct { eoi []byte } -func ctorLinux(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symbol, - ignores []*regexp.Regexp) (Reporter, error) { +func ctorLinux(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) { vmlinux := "" + var symbols map[string][]symbolizer.Symbol if kernelObj != "" { vmlinux = filepath.Join(kernelObj, "vmlinux") - if symbols == nil { - var err error - symbols, err = symbolizer.ReadSymbols(vmlinux) - if err != nil { - return nil, err - } + var err error + symbols, err = symbolizer.ReadSymbols(vmlinux) + if err != nil { + return nil, nil, err } } ctx := &linux{ @@ -95,7 +93,23 @@ func ctorLinux(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symb []byte("FAULT_INJECTION: forcing a failure"), []byte("FAULT_FLAG_ALLOW_RETRY missing"), } - return ctx, nil + suppressions := []string{ + "fatal error: runtime: out of memory", + "fatal error: runtime: cannot allocate memory", + "panic: failed to start executor binary", + "panic: executor failed: pthread_create failed", + "panic: failed to create temp dir", + "fatal error: unexpected signal during runtime execution", // presubmably OOM turned into SIGBUS + "signal SIGBUS: bus error", // presubmably OOM turned into SIGBUS + "Out of memory: Kill process .* \\(syz-fuzzer\\)", + "Out of memory: Kill process .* \\(sshd\\)", + "Killed process .* \\(syz-fuzzer\\)", + "Killed process .* \\(sshd\\)", + "lowmemorykiller: Killing 'syz-fuzzer'", + "lowmemorykiller: Killing 'sshd'", + "INIT: PANIC: segmentation violation!", + } + return ctx, suppressions, nil } func (ctx *linux) ContainsCrash(output []byte) bool { diff --git a/pkg/report/linux_test.go b/pkg/report/linux_test.go index 0543fcbe0..338ab27a0 100644 --- a/pkg/report/linux_test.go +++ b/pkg/report/linux_test.go @@ -5,38 +5,32 @@ package report import ( "fmt" - "regexp" "testing" "github.com/google/syzkaller/pkg/symbolizer" + "github.com/google/syzkaller/syz-manager/mgrconfig" ) func TestLinuxIgnores(t *testing.T) { - reporter, err := NewReporter("linux", "", "", "", nil, nil) + cfg := &mgrconfig.Config{ + TargetOS: "linux", + } + reporter, err := NewReporter(cfg) if err != nil { t.Fatal(err) } - ignores1 := []*regexp.Regexp{ - regexp.MustCompile("BUG: bug3"), - } - reporter1, err := NewReporter("linux", "", "", "", nil, ignores1) + cfg.Ignores = []string{"BUG: bug3"} + reporter1, err := NewReporter(cfg) if err != nil { t.Fatal(err) } - ignores2 := []*regexp.Regexp{ - regexp.MustCompile("BUG: bug3"), - regexp.MustCompile("BUG: bug1"), - } - reporter2, err := NewReporter("linux", "", "", "", nil, ignores2) + cfg.Ignores = []string{"BUG: bug3", "BUG: bug1"} + reporter2, err := NewReporter(cfg) if err != nil { t.Fatal(err) } - ignores3 := []*regexp.Regexp{ - regexp.MustCompile("BUG: bug3"), - regexp.MustCompile("BUG: bug1"), - regexp.MustCompile("BUG: bug2"), - } - reporter3, err := NewReporter("linux", "", "", "", nil, ignores3) + cfg.Ignores = []string{"BUG: bug3", "BUG: bug1", "BUG: bug2"} + reporter3, err := NewReporter(cfg) if err != nil { t.Fatal(err) } diff --git a/pkg/report/netbsd.go b/pkg/report/netbsd.go index 6c4dbedf9..5457327c9 100644 --- a/pkg/report/netbsd.go +++ b/pkg/report/netbsd.go @@ -5,26 +5,21 @@ package report import ( "regexp" - - "github.com/google/syzkaller/pkg/symbolizer" ) type netbsd struct { kernelSrc string kernelObj string - symbols map[string][]symbolizer.Symbol ignores []*regexp.Regexp } -func ctorNetbsd(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symbol, - ignores []*regexp.Regexp) (Reporter, error) { +func ctorNetbsd(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) { ctx := &netbsd{ kernelSrc: kernelSrc, kernelObj: kernelObj, - symbols: symbols, ignores: ignores, } - return ctx, nil + return ctx, nil, nil } func (ctx *netbsd) ContainsCrash(output []byte) bool { diff --git a/pkg/report/report.go b/pkg/report/report.go index bd702b1d0..2e8d13a0f 100644 --- a/pkg/report/report.go +++ b/pkg/report/report.go @@ -12,7 +12,7 @@ import ( "regexp" "strings" - "github.com/google/syzkaller/pkg/symbolizer" + "github.com/google/syzkaller/syz-manager/mgrconfig" ) type Reporter interface { @@ -37,6 +37,8 @@ type Report struct { // StartPos/EndPos denote region of output with oops message(s). StartPos int EndPos int + // Suppressed indicates whether the report should not be reported to user. + Suppressed bool // Corrupted indicates whether the report is truncated of corrupted in some other way. Corrupted bool // corruptedReason contains reason why the report is marked as corrupted. @@ -45,28 +47,29 @@ type Report struct { Maintainers []string } -// NewReporter creates reporter for the specified OS/vmType: -// kernelSrc: path to kernel sources directory -// kernelObj: path to kernel build directory (can be empty for in-tree build) -// symbols: kernel symbols (result of pkg/symbolizer.ReadSymbols on kernel object file) -// ignores: optional list of regexps to ignore (must match first line of crash message) -func NewReporter(os, vmType, kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symbol, - ignores []*regexp.Regexp) (Reporter, error) { - if vmType == "gvisor" { - os = vmType +// NewReporter creates reporter for the specified OS/Type. +func NewReporter(cfg *mgrconfig.Config) (Reporter, error) { + typ := cfg.TargetOS + if cfg.Type == "gvisor" { + typ = cfg.Type } - ctor := ctors[os] + ctor := ctors[typ] if ctor == nil { - return nil, fmt.Errorf("unknown os: %v", os) + return nil, fmt.Errorf("unknown OS: %v", typ) } - if kernelObj == "" { - kernelObj = kernelSrc // assume in-tree build + ignores, err := compileRegexps(cfg.Ignores) + if err != nil { + return nil, err + } + rep, suppressions, err := ctor(cfg.KernelSrc, cfg.KernelObj, ignores) + if err != nil { + return nil, err } - rep, err := ctor(kernelSrc, kernelObj, symbols, ignores) + supps, err := compileRegexps(append(suppressions, cfg.Suppressions...)) if err != nil { return nil, err } - return reporterWrapper{rep}, nil + return reporterWrapper{rep, supps}, nil } var ctors = map[string]fn{ @@ -79,10 +82,23 @@ var ctors = map[string]fn{ "windows": ctorStub, } -type fn func(string, string, map[string][]symbolizer.Symbol, []*regexp.Regexp) (Reporter, error) +type fn func(string, string, []*regexp.Regexp) (Reporter, []string, error) + +func compileRegexps(list []string) ([]*regexp.Regexp, error) { + compiled := make([]*regexp.Regexp, len(list)) + for i, str := range list { + re, err := regexp.Compile(str) + if err != nil { + return nil, fmt.Errorf("failed to compile %q: %v", str, err) + } + compiled[i] = re + } + return compiled, nil +} type reporterWrapper struct { Reporter + suppressions []*regexp.Regexp } func (wrap reporterWrapper) Parse(output []byte) *Report { @@ -91,6 +107,7 @@ func (wrap reporterWrapper) Parse(output []byte) *Report { return nil } rep.Title = sanitizeTitle(replaceTable(dynamicTitleReplacement, rep.Title)) + rep.Suppressed = matchesAny(rep.Output, wrap.suppressions) return rep } diff --git a/pkg/report/report_test.go b/pkg/report/report_test.go index 14d6c45ce..a2d833837 100644 --- a/pkg/report/report_test.go +++ b/pkg/report/report_test.go @@ -16,6 +16,7 @@ import ( "testing" "github.com/google/syzkaller/pkg/osutil" + "github.com/google/syzkaller/syz-manager/mgrconfig" ) var flagUpdate = flag.Bool("update", false, "update test files accordingly to current results") @@ -214,7 +215,10 @@ func forEachFile(t *testing.T, dir string, fn func(t *testing.T, reporter Report if err != nil { t.Fatal(err) } - reporter, err := NewReporter(os, "", "", "", nil, nil) + cfg := &mgrconfig.Config{ + TargetOS: os, + } + reporter, err := NewReporter(cfg) if err != nil { t.Fatal(err) } diff --git a/pkg/report/stub.go b/pkg/report/stub.go index 04f17084a..32bcb0085 100644 --- a/pkg/report/stub.go +++ b/pkg/report/stub.go @@ -5,26 +5,21 @@ package report import ( "regexp" - - "github.com/google/syzkaller/pkg/symbolizer" ) type stub struct { kernelSrc string kernelObj string - symbols map[string][]symbolizer.Symbol ignores []*regexp.Regexp } -func ctorStub(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Symbol, - ignores []*regexp.Regexp) (Reporter, error) { +func ctorStub(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) { ctx := &stub{ kernelSrc: kernelSrc, kernelObj: kernelObj, - symbols: symbols, ignores: ignores, } - return ctx, nil + return ctx, nil, nil } func (ctx *stub) ContainsCrash(output []byte) bool { -- cgit mrf-deployment