aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/cover
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2024-03-15 19:53:15 +0100
committerAleksandr Nogikh <nogikh@google.com>2024-03-25 13:12:00 +0000
commit409ee912f2c4f07e3064b4e6f4a83e1f812531d8 (patch)
treeef7701845a10852597eb2fbf3c962d27f47ca161 /pkg/cover
parent5d5b1ae5147428cf089a616a3114af1add92068d (diff)
all: move fuzzer to the host
Instead of doing fuzzing in parallel in running VM, make all decisions in the host syz-manager process. Instantiate and keep a fuzzer.Fuzzer object in syz-manager and update the RPC between syz-manager and syz-fuzzer to exchange exact programs to execute and their resulting signal and coverage. To optimize the networking traffic, exchange mostly only the difference between the known max signal and the detected signal.
Diffstat (limited to 'pkg/cover')
-rw-r--r--pkg/cover/canonicalizer.go38
-rw-r--r--pkg/cover/canonicalizer_test.go46
2 files changed, 25 insertions, 59 deletions
diff --git a/pkg/cover/canonicalizer.go b/pkg/cover/canonicalizer.go
index c7c385aed..d3b014af8 100644
--- a/pkg/cover/canonicalizer.go
+++ b/pkg/cover/canonicalizer.go
@@ -9,7 +9,6 @@ import (
"github.com/google/syzkaller/pkg/host"
"github.com/google/syzkaller/pkg/log"
- "github.com/google/syzkaller/pkg/signal"
)
type Canonicalizer struct {
@@ -120,18 +119,18 @@ func (can *Canonicalizer) NewInstance(modules []host.KernelModule) *Canonicalize
}
}
-func (ci *CanonicalizerInstance) Canonicalize(cov []uint32, sign signal.Serial) ([]uint32, signal.Serial) {
+func (ci *CanonicalizerInstance) Canonicalize(elems []uint32) []uint32 {
if ci.canonical.moduleKeys == nil {
- return cov, sign
+ return elems
}
- return ci.canonicalize.convertPCs(cov, sign)
+ return ci.canonicalize.convertPCs(elems)
}
-func (ci *CanonicalizerInstance) Decanonicalize(cov []uint32, sign signal.Serial) ([]uint32, signal.Serial) {
+func (ci *CanonicalizerInstance) Decanonicalize(elems []uint32) []uint32 {
if ci.canonical.moduleKeys == nil {
- return cov, sign
+ return elems
}
- return ci.decanonicalize.convertPCs(cov, sign)
+ return ci.decanonicalize.convertPCs(elems)
}
func (ci *CanonicalizerInstance) DecanonicalizeFilter(bitmap map[uint32]uint32) map[uint32]uint32 {
@@ -177,34 +176,21 @@ func findModule(pc uint32, moduleKeys []uint32) (moduleIdx int) {
return moduleIdx - 1
}
-func (convert *Convert) convertPCs(cov []uint32, sign signal.Serial) ([]uint32, signal.Serial) {
+func (convert *Convert) convertPCs(pcs []uint32) []uint32 {
// Convert coverage.
- var retCov []uint32
+ var ret []uint32
convCtx := &convertContext{convert: convert}
- for _, pc := range cov {
+ for _, pc := range pcs {
if newPC, ok := convert.convertPC(pc); ok {
- retCov = append(retCov, newPC)
+ ret = append(ret, newPC)
} else {
convCtx.discard(pc)
}
}
if msg := convCtx.discarded(); msg != "" {
- log.Logf(4, "error in PC conversion: %v", msg)
- }
- // Convert signals.
- retSign := &signal.Serial{}
- convCtx = &convertContext{convert: convert}
- for idx, elem := range sign.Elems {
- if newSign, ok := convert.convertPC(uint32(elem)); ok {
- retSign.AddElem(newSign, sign.Prios[idx])
- } else {
- convCtx.discard(uint32(elem))
- }
- }
- if msg := convCtx.discarded(); msg != "" {
- log.Logf(4, "error in signal conversion: %v", msg)
+ log.Logf(4, "error in PC/signal conversion: %v", msg)
}
- return retCov, *retSign
+ return ret
}
func (convert *Convert) convertPC(pc uint32) (uint32, bool) {
diff --git a/pkg/cover/canonicalizer_test.go b/pkg/cover/canonicalizer_test.go
index db418abe1..aa840a96f 100644
--- a/pkg/cover/canonicalizer_test.go
+++ b/pkg/cover/canonicalizer_test.go
@@ -13,7 +13,6 @@ import (
"github.com/google/syzkaller/pkg/cover"
"github.com/google/syzkaller/pkg/host"
- "github.com/google/syzkaller/pkg/signal"
)
type RPCServer struct {
@@ -28,8 +27,8 @@ type Fuzzer struct {
goalCov []uint32
bitmap map[uint32]uint32
goalBitmap map[uint32]uint32
- sign signal.Serial
- goalSign signal.Serial
+ sign []uint32
+ goalSign []uint32
}
type canonicalizeValue int
@@ -49,13 +48,9 @@ func TestNilModules(t *testing.T) {
serv.fuzzers["f1"].cov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
serv.fuzzers["f1"].goalCov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
- serv.fuzzers["f1"].sign = signal.FromRaw(serv.fuzzers["f1"].cov, 0).Serialize()
- serv.fuzzers["f1"].goalSign = signal.FromRaw(serv.fuzzers["f1"].goalCov, 0).Serialize()
serv.fuzzers["f2"].cov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
serv.fuzzers["f2"].goalCov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
- 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,
@@ -87,15 +82,15 @@ func TestNilModules(t *testing.T) {
}
serv.fuzzers["f1"].goalCov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
- serv.fuzzers["f1"].goalSign = signal.FromRaw(serv.fuzzers["f1"].goalCov, 0).Serialize()
+ serv.fuzzers["f1"].goalSign = serv.fuzzers["f1"].goalCov
serv.fuzzers["f2"].goalCov = []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
- serv.fuzzers["f2"].goalSign = signal.FromRaw(serv.fuzzers["f2"].goalCov, 0).Serialize()
+ serv.fuzzers["f2"].goalSign = serv.fuzzers["f2"].goalCov
if err := serv.runTest(Decanonicalize); err != "" {
t.Fatalf("failed in decanonicalization: %v", err)
}
}
-// Confirms there is no change to signals if coverage is disabled and fallback signals are used.
+// Confirms there is no change to PCs if coverage is disabled and fallback signals are used.
func TestDisabledSignals(t *testing.T) {
serv := &RPCServer{
fuzzers: make(map[string]*Fuzzer),
@@ -112,18 +107,18 @@ func TestDisabledSignals(t *testing.T) {
serv.connect("f2", f2Modules, false)
pcs := []uint32{0x00010000, 0x00020000, 0x00030000, 0x00040000}
- serv.fuzzers["f1"].sign = signal.FromRaw(pcs, 0).Serialize()
- serv.fuzzers["f1"].goalSign = signal.FromRaw(pcs, 0).Serialize()
+ serv.fuzzers["f1"].cov = pcs
+ serv.fuzzers["f1"].goalCov = pcs
- serv.fuzzers["f2"].sign = signal.FromRaw(pcs, 0).Serialize()
- serv.fuzzers["f2"].goalSign = signal.FromRaw(pcs, 0).Serialize()
+ serv.fuzzers["f2"].sign = pcs
+ serv.fuzzers["f2"].goalSign = pcs
if err := serv.runTest(Canonicalize); err != "" {
t.Fatalf("failed in canonicalization: %v", err)
}
- serv.fuzzers["f1"].goalSign = signal.FromRaw(pcs, 0).Serialize()
- serv.fuzzers["f2"].goalSign = signal.FromRaw(pcs, 0).Serialize()
+ serv.fuzzers["f1"].goalSign = pcs
+ serv.fuzzers["f2"].goalSign = pcs
if err := serv.runTest(Decanonicalize); err != "" {
t.Fatalf("failed in decanonicalization: %v", err)
}
@@ -152,8 +147,6 @@ func TestModules(t *testing.T) {
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
serv.fuzzers["f1"].goalCov = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
- serv.fuzzers["f1"].sign = signal.FromRaw(serv.fuzzers["f1"].cov, 0).Serialize()
- serv.fuzzers["f1"].goalSign = signal.FromRaw(serv.fuzzers["f1"].goalCov, 0).Serialize()
// The modules addresss are inverted between: (2 and 4), (3 and 5),
// affecting the output canonical coverage values in these ranges.
@@ -161,8 +154,6 @@ func TestModules(t *testing.T) {
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
serv.fuzzers["f2"].goalCov = []uint32{0x00010000, 0x00015000, 0x00040000, 0x00025000, 0x00045000,
0x0004a000, 0x00020000, 0x00030000, 0x0003b000, 0x00055000}
- 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,
@@ -195,10 +186,8 @@ func TestModules(t *testing.T) {
serv.fuzzers["f1"].goalCov = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
- serv.fuzzers["f1"].goalSign = signal.FromRaw(serv.fuzzers["f1"].goalCov, 0).Serialize()
serv.fuzzers["f2"].goalCov = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000, 0x00030000,
0x00035000, 0x00040000, 0x00045000, 0x00050000, 0x00055000}
- serv.fuzzers["f2"].goalSign = signal.FromRaw(serv.fuzzers["f2"].goalCov, 0).Serialize()
if err := serv.runTest(Decanonicalize); err != "" {
t.Fatalf("failed in decanonicalization: %v", err)
}
@@ -225,15 +214,12 @@ func TestChangingModules(t *testing.T) {
// in this range should be deleted.
serv.fuzzers["f2"].cov = []uint32{0x00010000, 0x00015000, 0x00020000, 0x00025000}
serv.fuzzers["f2"].goalCov = []uint32{0x00010000, 0x00015000, 0x00025000}
- serv.fuzzers["f2"].sign = signal.FromRaw(serv.fuzzers["f2"].cov, 0).Serialize()
- serv.fuzzers["f2"].goalSign = signal.FromRaw(serv.fuzzers["f2"].goalCov, 0).Serialize()
if err := serv.runTest(Canonicalize); err != "" {
t.Fatalf("failed in canonicalization: %v", err)
}
serv.fuzzers["f2"].goalCov = []uint32{0x00010000, 0x00015000, 0x00025000}
- serv.fuzzers["f2"].goalSign = signal.FromRaw(serv.fuzzers["f2"].goalCov, 0).Serialize()
if err := serv.runTest(Decanonicalize); err != "" {
t.Fatalf("failed in decanonicalization: %v", err)
}
@@ -241,12 +227,11 @@ func TestChangingModules(t *testing.T) {
func (serv *RPCServer) runTest(val canonicalizeValue) string {
var cov []uint32
- var sign signal.Serial
for name, fuzzer := range serv.fuzzers {
if val == Canonicalize {
- cov, sign = fuzzer.instModules.Canonicalize(fuzzer.cov, fuzzer.sign)
+ cov = fuzzer.instModules.Canonicalize(fuzzer.cov)
} else {
- cov, sign = fuzzer.instModules.Decanonicalize(fuzzer.cov, fuzzer.sign)
+ cov = fuzzer.instModules.Decanonicalize(fuzzer.cov)
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",
@@ -257,12 +242,7 @@ func (serv *RPCServer) runTest(val canonicalizeValue) string {
return fmt.Sprintf("failed in coverage conversion. Fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x",
name, fuzzer.goalCov, cov)
}
- if !reflect.DeepEqual(sign.Deserialize(), fuzzer.goalSign.Deserialize()) {
- return fmt.Sprintf("failed in signal conversion. Fuzzer %v.\nExpected: 0x%x.\nReturned: 0x%x",
- name, fuzzer.goalSign, sign)
- }
fuzzer.cov = cov
- fuzzer.sign = sign
}
return ""
}