diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2023-01-31 13:38:10 +0100 |
|---|---|---|
| committer | Aleksandr Nogikh <wp32pw@gmail.com> | 2023-02-10 14:34:44 +0100 |
| commit | ad871703d4fcd9ed84544dd6f5c4221aa5df5feb (patch) | |
| tree | e56c0441a09c3d6d3cd90ec9e290b9abe65f3d82 /pkg/subsystem/extractor.go | |
| parent | 9a724c34f06b47f05b36c5292b107e9b06048667 (diff) | |
pkg/subsystem: extract subsystems from a crash list
For now, let's use a straightforward approach:
1) Extract all subsystems for each guilty path and syz reproducer.
2) If there are both parents and children in the list, remove parents.
3) Count the remaining subsystems.
4) Pick the ones that appear most often.
Diffstat (limited to 'pkg/subsystem/extractor.go')
| -rw-r--r-- | pkg/subsystem/extractor.go | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/pkg/subsystem/extractor.go b/pkg/subsystem/extractor.go new file mode 100644 index 000000000..e54086b29 --- /dev/null +++ b/pkg/subsystem/extractor.go @@ -0,0 +1,74 @@ +// Copyright 2023 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 subsystem + +import ( + "github.com/google/syzkaller/pkg/subsystem/entity" +) + +// Extractor deduces the subsystems from the list of crashes. +type Extractor struct { + raw rawExtractorInterface +} + +// Crash represents the subset of the available crash information that's required for +// subsystem inference. +type Crash struct { + GuiltyPath string + SyzRepro []byte +} + +// rawExtractorInterface simplifies testing. +type rawExtractorInterface interface { + FromPath(path string) []*entity.Subsystem + FromProg(progBytes []byte) []*entity.Subsystem +} + +func MakeExtractor(list []*entity.Subsystem) *Extractor { + return &Extractor{raw: makeRawExtractor(list)} +} + +func (e *Extractor) Extract(crashes []*Crash) []*entity.Subsystem { + // First put all subsystems to the same list. + subsystems := []*entity.Subsystem{} + for _, crash := range crashes { + if crash.GuiltyPath != "" { + subsystems = append(subsystems, e.raw.FromPath(crash.GuiltyPath)...) + } + if len(crash.SyzRepro) > 0 { + subsystems = append(subsystems, e.raw.FromProg(crash.SyzRepro)...) + } + } + + // If there are both parents and children, remove parents. + ignore := make(map[*entity.Subsystem]struct{}) + for _, entry := range subsystems { + for p := range entry.ReachableParents() { + ignore[p] = struct{}{} + } + } + + // And calculate counts. + counts := make(map[*entity.Subsystem]int) + maxCount := 0 + for _, entry := range subsystems { + if _, ok := ignore[entry]; ok { + continue + } + counts[entry]++ + if counts[entry] > maxCount { + maxCount = counts[entry] + } + } + + // Pick the most prevalent ones. + ret := []*entity.Subsystem{} + for entry, count := range counts { + if count < maxCount { + continue + } + ret = append(ret, entry) + } + return ret +} |
