diff options
Diffstat (limited to 'syz-manager')
| -rw-r--r-- | syz-manager/cover.go | 48 | ||||
| -rw-r--r-- | syz-manager/covfilter.go | 152 | ||||
| -rw-r--r-- | syz-manager/http.go | 15 | ||||
| -rw-r--r-- | syz-manager/manager.go | 13 |
4 files changed, 23 insertions, 205 deletions
diff --git a/syz-manager/cover.go b/syz-manager/cover.go deleted file mode 100644 index 19ae5f668..000000000 --- a/syz-manager/cover.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2015 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 main - -import ( - "sync" - - "github.com/google/syzkaller/pkg/cover" - "github.com/google/syzkaller/pkg/cover/backend" - "github.com/google/syzkaller/pkg/log" - "github.com/google/syzkaller/pkg/mgrconfig" - "github.com/google/syzkaller/pkg/vminfo" -) - -var ( - cachedRepGenMu sync.Mutex - cachedRepGen *cover.ReportGenerator -) - -func getReportGenerator(cfg *mgrconfig.Config, modules []*vminfo.KernelModule) (*cover.ReportGenerator, error) { - cachedRepGenMu.Lock() - defer cachedRepGenMu.Unlock() - if cachedRepGen == nil { - log.Logf(0, "initializing coverage information...") - rg, err := cover.MakeReportGenerator(cfg, cfg.KernelSubsystem, modules, cfg.RawCover) - if err != nil { - return nil, err - } - cachedRepGen = rg - } - return cachedRepGen, nil -} - -func resetReportGenerator() { - cachedRepGenMu.Lock() - defer cachedRepGenMu.Unlock() - cachedRepGen = nil -} - -func coverToPCs(cfg *mgrconfig.Config, cov []uint64) []uint64 { - pcs := make([]uint64, 0, len(cov)) - for _, pc := range cov { - prev := backend.PreviousInstructionPC(cfg.SysTarget, cfg.Type, pc) - pcs = append(pcs, prev) - } - return pcs -} diff --git a/syz-manager/covfilter.go b/syz-manager/covfilter.go deleted file mode 100644 index ca6e4175a..000000000 --- a/syz-manager/covfilter.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2020 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 main - -import ( - "bufio" - "fmt" - "os" - "regexp" - "sort" - "strconv" - - "github.com/google/syzkaller/pkg/cover/backend" - "github.com/google/syzkaller/pkg/log" - "github.com/google/syzkaller/pkg/mgrconfig" - "github.com/google/syzkaller/pkg/vminfo" -) - -func (mgr *Manager) CoverageFilter(modules []*vminfo.KernelModule) []uint64 { - execFilter, filter, err := createCoverageFilter(mgr.cfg, modules) - if err != nil { - log.Fatalf("failed to init coverage filter: %v", err) - } - mgr.modules = modules - mgr.coverFilter = filter - return execFilter -} - -func createCoverageFilter(cfg *mgrconfig.Config, modules []*vminfo.KernelModule) ([]uint64, - map[uint64]struct{}, error) { - if !cfg.HasCovFilter() { - return nil, nil, nil - } - // Always initialize ReportGenerator because RPCServer.NewInput will need it to filter coverage. - rg, err := getReportGenerator(cfg, modules) - if err != nil { - return nil, nil, err - } - pcs := make(map[uint64]struct{}) - foreachSymbol := func(apply func(*backend.ObjectUnit)) { - for _, sym := range rg.Symbols { - apply(&sym.ObjectUnit) - } - } - if err := covFilterAddFilter(pcs, cfg.CovFilter.Functions, foreachSymbol); err != nil { - return nil, nil, err - } - foreachUnit := func(apply func(*backend.ObjectUnit)) { - for _, unit := range rg.Units { - apply(&unit.ObjectUnit) - } - } - if err := covFilterAddFilter(pcs, cfg.CovFilter.Files, foreachUnit); err != nil { - return nil, nil, err - } - if err := covFilterAddRawPCs(pcs, cfg.CovFilter.RawPCs); err != nil { - return nil, nil, err - } - // Copy pcs into execPCs. This is used to filter coverage in the executor. - execPCs := make([]uint64, 0, len(pcs)) - for pc := range pcs { - execPCs = append(execPCs, pc) - } - // PCs from CMPs are deleted to calculate `filtered coverage` statistics. - for _, sym := range rg.Symbols { - for _, pc := range sym.CMPs { - delete(pcs, pc) - } - } - return execPCs, pcs, nil -} - -func covFilterAddFilter(pcs map[uint64]struct{}, filters []string, foreach func(func(*backend.ObjectUnit))) error { - res, err := compileRegexps(filters) - if err != nil { - return err - } - used := make(map[*regexp.Regexp][]string) - foreach(func(unit *backend.ObjectUnit) { - for _, re := range res { - if re.MatchString(unit.Name) { - // We add both coverage points and comparison interception points - // because executor filters comparisons as well. - for _, pc := range unit.PCs { - pcs[pc] = struct{}{} - } - for _, pc := range unit.CMPs { - pcs[pc] = struct{}{} - } - used[re] = append(used[re], unit.Name) - break - } - } - }) - for _, re := range res { - sort.Strings(used[re]) - log.Logf(0, "coverage filter: %v: %v", re, used[re]) - } - if len(res) != len(used) { - return fmt.Errorf("some filters don't match anything") - } - return nil -} - -func covFilterAddRawPCs(pcs map[uint64]struct{}, rawPCsFiles []string) error { - re := regexp.MustCompile(`(0x[0-9a-f]+)(?:: (0x[0-9a-f]+))?`) - for _, f := range rawPCsFiles { - rawFile, err := os.Open(f) - if err != nil { - return fmt.Errorf("failed to open raw PCs file: %w", err) - } - defer rawFile.Close() - s := bufio.NewScanner(rawFile) - for s.Scan() { - match := re.FindStringSubmatch(s.Text()) - if match == nil { - return fmt.Errorf("bad line: %q", s.Text()) - } - pc, err := strconv.ParseUint(match[1], 0, 64) - if err != nil { - return err - } - weight, err := strconv.ParseUint(match[2], 0, 32) - if match[2] != "" && err != nil { - return err - } - // If no weight is detected, set the weight to 0x1 by default. - if match[2] == "" || weight < 1 { - weight = 1 - } - _ = weight // currently unused - pcs[pc] = struct{}{} - } - if err := s.Err(); err != nil { - return err - } - } - return nil -} - -func compileRegexps(regexpStrings []string) ([]*regexp.Regexp, error) { - var regexps []*regexp.Regexp - for _, rs := range regexpStrings { - r, err := regexp.Compile(rs) - if err != nil { - return nil, fmt.Errorf("failed to compile regexp: %w", err) - } - regexps = append(regexps, r) - } - return regexps, nil -} diff --git a/syz-manager/http.go b/syz-manager/http.go index 288d043fc..2e5f703a9 100644 --- a/syz-manager/http.go +++ b/syz-manager/http.go @@ -24,6 +24,7 @@ import ( "github.com/google/syzkaller/pkg/fuzzer" "github.com/google/syzkaller/pkg/html/pages" "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/pkg/manager" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/stat" "github.com/google/syzkaller/pkg/vcs" @@ -332,7 +333,7 @@ func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, funcF return } - rg, err := getReportGenerator(mgr.cfg, mgr.modules) + rg, err := mgr.reportGenerator.Get() if err != nil { http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError) return @@ -340,7 +341,7 @@ func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, funcF if r.FormValue("flush") != "" { defer func() { - resetReportGenerator() + mgr.reportGenerator.Reset() debug.FreeOSMemory() }() } @@ -362,13 +363,13 @@ func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, funcF progs = append(progs, cover.Prog{ Sig: sig, Data: string(inp.Prog.Serialize()), - PCs: coverToPCs(mgr.cfg, inp.Updates[updateID].RawCover), + PCs: manager.CoverToPCs(mgr.cfg, inp.Updates[updateID].RawCover), }) } else { progs = append(progs, cover.Prog{ Sig: sig, Data: string(inp.Prog.Serialize()), - PCs: coverToPCs(mgr.cfg, inp.Cover), + PCs: manager.CoverToPCs(mgr.cfg, inp.Cover), }) } } else { @@ -380,7 +381,7 @@ func (mgr *Manager) httpCoverCover(w http.ResponseWriter, r *http.Request, funcF progs = append(progs, cover.Prog{ Sig: inp.Sig, Data: string(inp.Prog.Serialize()), - PCs: coverToPCs(mgr.cfg, inp.Cover), + PCs: manager.CoverToPCs(mgr.cfg, inp.Cover), }) } } @@ -562,6 +563,10 @@ func (mgr *Manager) httpDebugInput(w http.ResponseWriter, r *http.Request) { } func (mgr *Manager) modulesInfo(w http.ResponseWriter, r *http.Request) { + if !mgr.checkDone.Load() { + http.Error(w, "info is not ready, please try again later after fuzzer started", http.StatusInternalServerError) + return + } modules, err := json.MarshalIndent(mgr.modules, "", "\t") if err != nil { fmt.Fprintf(w, "unable to create JSON modules info: %v", err) diff --git a/syz-manager/manager.go b/syz-manager/manager.go index d88ca816e..db181d3a3 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -89,6 +89,7 @@ type Manager struct { crashTypes map[string]bool enabledFeatures flatrpc.Feature checkDone atomic.Bool + reportGenerator *manager.ReportGeneratorWrapper fresh bool expertMode bool modules []*vminfo.KernelModule @@ -229,6 +230,7 @@ func RunManager(mode Mode, cfg *mgrconfig.Config) { externalReproQueue: make(chan *manager.Crash, 10), crashes: make(chan *manager.Crash, 10), saturatedCalls: make(map[string]bool), + reportGenerator: manager.ReportGeneratorCache(cfg), } if *flagDebug { @@ -1424,6 +1426,17 @@ func (mgr *Manager) dashboardReproTasks() { } } +func (mgr *Manager) CoverageFilter(modules []*vminfo.KernelModule) []uint64 { + mgr.reportGenerator.Init(modules) + execFilter, filter, err := manager.CreateCoverageFilter(mgr.reportGenerator, mgr.cfg.CovFilter) + if err != nil { + log.Fatalf("failed to init coverage filter: %v", err) + } + mgr.modules = modules + mgr.coverFilter = filter + return execFilter +} + func publicWebAddr(addr string) string { _, port, err := net.SplitHostPort(addr) if err == nil && port != "" { |
