From 52ae002a69946d44626bb626463c27ea196a6551 Mon Sep 17 00:00:00 2001 From: Liz Prucka Date: Tue, 16 May 2023 16:05:06 -0500 Subject: pkg/cover, syz-manager: support coverage filtering with modules Apply module conversion to filter bitmap to support coverage filtering when modules are used. Coverage bitmap is decanonicalized to match each instance's module PCs. This was done by decanonicalizing the map of bitmap PCs before bitmap creation to simplify conversion. I could convert the final bitmap or pass in the canonicalization instance to createCoverageFilter() to prevent this change. The "coverFilter" used by the manager is only used on canonicalized PCs, so it remains unchanged. --- pkg/cover/canonicalizer.go | 12 +++++++++ pkg/cover/canonicalizer_test.go | 57 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) (limited to 'pkg') diff --git a/pkg/cover/canonicalizer.go b/pkg/cover/canonicalizer.go index 48b1bb3df..758ab5593 100644 --- a/pkg/cover/canonicalizer.go +++ b/pkg/cover/canonicalizer.go @@ -117,6 +117,18 @@ func (ci *CanonicalizerInstance) Decanonicalize(cov []uint32, sign signal.Serial ci.decanonicalize.convertPCs(cov, sign) } +func (ci *CanonicalizerInstance) DecanonicalizeFilter(bitmap map[uint32]uint32) map[uint32]uint32 { + // Skip conversion if modules or filter are not used. + if ci.canonical.moduleKeys == nil || len(bitmap) == 0 { + return bitmap + } + instBitmap := make(map[uint32]uint32) + for pc, val := range bitmap { + instBitmap[ci.decanonicalize.convertPC(pc)] = val + } + return instBitmap +} + // Store sorted list of addresses. Used to binary search when converting PCs. func setModuleKeys(moduleKeys []uint32, modules []host.KernelModule) { for idx, module := range modules { diff --git a/pkg/cover/canonicalizer_test.go b/pkg/cover/canonicalizer_test.go index 78356535c..c9e208dcc 100644 --- a/pkg/cover/canonicalizer_test.go +++ b/pkg/cover/canonicalizer_test.go @@ -26,6 +26,8 @@ type Fuzzer struct { instModules *cover.CanonicalizerInstance cov []uint32 goalCov []uint32 + bitmap map[uint32]uint32 + goalBitmap map[uint32]uint32 sign signal.Serial goalSign signal.Serial } @@ -55,6 +57,31 @@ func TestNilModules(t *testing.T) { serv.fuzzers["f2"].sign = signal.FromRaw(serv.fuzzers["f2"].cov, 0).Serialize() serv.fuzzers["f2"].goalSign = signal.FromRaw(serv.fuzzers["f2"].goalCov, 0).Serialize() + serv.fuzzers["f1"].bitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00020FFF: 2, + 0x00030000: 3, + 0x00040000: 4, + } + serv.fuzzers["f1"].goalBitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00020FFF: 2, + 0x00030000: 3, + 0x00040000: 4, + } + serv.fuzzers["f2"].bitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00020FFF: 2, + 0x00030000: 3, + 0x00040000: 4, + } + serv.fuzzers["f2"].goalBitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00020FFF: 2, + 0x00030000: 3, + 0x00040000: 4, + } + if err := serv.runTest(Canonicalize); err != "" { t.Fatalf("failed in canonicalization: %v", err) } @@ -137,6 +164,31 @@ func TestModules(t *testing.T) { serv.fuzzers["f2"].sign = signal.FromRaw(serv.fuzzers["f2"].cov, 0).Serialize() serv.fuzzers["f2"].goalSign = signal.FromRaw(serv.fuzzers["f2"].goalCov, 0).Serialize() + serv.fuzzers["f1"].bitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00020FFF: 2, + 0x00030000: 3, + 0x00040000: 4, + } + serv.fuzzers["f1"].goalBitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00020FFF: 2, + 0x00030000: 3, + 0x00040000: 4, + } + serv.fuzzers["f2"].bitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00020FFF: 2, + 0x00030000: 3, + 0x00040000: 4, + } + serv.fuzzers["f2"].goalBitmap = map[uint32]uint32{ + 0x00010011: 1, + 0x00040FFF: 2, + 0x00045000: 3, + 0x00020000: 4, + } + if err := serv.runTest(Canonicalize); err != "" { t.Fatalf("failed in canonicalization: %v", err) } @@ -158,6 +210,11 @@ func (serv *RPCServer) runTest(val canonicalizeValue) string { fuzzer.instModules.Canonicalize(fuzzer.cov, fuzzer.sign) } else { fuzzer.instModules.Decanonicalize(fuzzer.cov, fuzzer.sign) + instBitmap := fuzzer.instModules.DecanonicalizeFilter(fuzzer.bitmap) + if !reflect.DeepEqual(instBitmap, fuzzer.goalBitmap) { + return fmt.Sprintf("failed in bitmap conversion. Fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x", + name, fuzzer.goalBitmap, instBitmap) + } } if !reflect.DeepEqual(fuzzer.cov, fuzzer.goalCov) { return fmt.Sprintf("failed in coverage conversion. Fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x", -- cgit mrf-deployment