aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-05-29 11:28:03 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-06-03 15:04:36 +0000
commit2addfcda6297288cd48c399dfbef1f5752162011 (patch)
tree30a7d6f2f7d3bea992ebe1c38e698d1862ec44be /pkg
parentf0e94da92f1381e56ecd1c28575aaac54cdfc79d (diff)
syz-manager: add corpus triage mode
Add corpus triage mode and support it in testbed. This is useful to benchmark just the triage phase w/o any subsequent fuzzing. First, fuzzing is more random. Second, if triage duration is different in different versions, then they will do different amount of fuzzing in fixed testbed time.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/fuzzer/fuzzer.go16
-rw-r--r--pkg/fuzzer/queue/queue.go11
-rw-r--r--pkg/fuzzer/queue/queue_test.go12
-rw-r--r--pkg/fuzzer/stats.go43
4 files changed, 36 insertions, 46 deletions
diff --git a/pkg/fuzzer/fuzzer.go b/pkg/fuzzer/fuzzer.go
index 9ad218433..8be912139 100644
--- a/pkg/fuzzer/fuzzer.go
+++ b/pkg/fuzzer/fuzzer.go
@@ -76,7 +76,7 @@ type execQueues struct {
func newExecQueues(fuzzer *Fuzzer) execQueues {
ret := execQueues{
triageCandidateQueue: queue.DynamicOrder(),
- candidateQueue: queue.PlainWithStat(fuzzer.StatCandidates),
+ candidateQueue: queue.Plain(),
triageQueue: queue.DynamicOrder(),
smashQueue: queue.Plain(),
}
@@ -92,6 +92,10 @@ func newExecQueues(fuzzer *Fuzzer) execQueues {
return ret
}
+func (fuzzer *Fuzzer) CandidateTriageFinished() bool {
+ return fuzzer.statCandidates.Val()+fuzzer.statJobsTriageCandidate.Val() == 0
+}
+
func (fuzzer *Fuzzer) execute(executor queue.Executor, req *queue.Request) *queue.Result {
return fuzzer.executeWithFlags(executor, req, 0)
}
@@ -130,6 +134,9 @@ func (fuzzer *Fuzzer) processResult(req *queue.Request, res *queue.Result, flags
if res.Info != nil {
fuzzer.statExecTime.Add(int(res.Info.Elapsed / 1e6))
}
+ if flags&progCandidate != 0 {
+ fuzzer.statCandidates.Add(-1)
+ }
}
type Config struct {
@@ -161,11 +168,11 @@ func (fuzzer *Fuzzer) triageProgCall(p *prog.Prog, info *flatrpc.CallInfo, call
}
fuzzer.Logf(2, "found new signal in call %d in %s", call, p)
- queue := fuzzer.triageQueue
+ queue, stat := fuzzer.triageQueue, fuzzer.statJobsTriage
if flags&progCandidate > 0 {
- queue = fuzzer.triageCandidateQueue
+ queue, stat = fuzzer.triageCandidateQueue, fuzzer.statJobsTriageCandidate
}
- fuzzer.startJob(fuzzer.statJobsTriage, &triageJob{
+ fuzzer.startJob(stat, &triageJob{
p: p.Clone(),
call: call,
info: info,
@@ -243,6 +250,7 @@ type Candidate struct {
}
func (fuzzer *Fuzzer) AddCandidates(candidates []Candidate) {
+ fuzzer.statCandidates.Add(len(candidates))
for _, candidate := range candidates {
req, flags := candidateRequest(fuzzer, candidate)
fuzzer.enqueue(fuzzer.candidateQueue, req, flags)
diff --git a/pkg/fuzzer/queue/queue.go b/pkg/fuzzer/queue/queue.go
index a9411c1bd..cb70f5a9b 100644
--- a/pkg/fuzzer/queue/queue.go
+++ b/pkg/fuzzer/queue/queue.go
@@ -173,7 +173,6 @@ type Source interface {
// PlainQueue is a straighforward thread-safe Request queue implementation.
type PlainQueue struct {
- stat *stats.Val
mu sync.Mutex
queue []*Request
pos int
@@ -183,10 +182,6 @@ func Plain() *PlainQueue {
return &PlainQueue{}
}
-func PlainWithStat(val *stats.Val) *PlainQueue {
- return &PlainQueue{stat: val}
-}
-
func (pq *PlainQueue) Len() int {
pq.mu.Lock()
defer pq.mu.Unlock()
@@ -194,9 +189,6 @@ func (pq *PlainQueue) Len() int {
}
func (pq *PlainQueue) Submit(req *Request) {
- if pq.stat != nil {
- pq.stat.Add(1)
- }
pq.mu.Lock()
defer pq.mu.Unlock()
@@ -235,9 +227,6 @@ func (pq *PlainQueue) nextLocked() *Request {
ret := pq.queue[pq.pos]
pq.queue[pq.pos] = nil
pq.pos++
- if pq.stat != nil {
- pq.stat.Add(-1)
- }
return ret
}
diff --git a/pkg/fuzzer/queue/queue_test.go b/pkg/fuzzer/queue/queue_test.go
index a89ec0d3d..5b6a03ed0 100644
--- a/pkg/fuzzer/queue/queue_test.go
+++ b/pkg/fuzzer/queue/queue_test.go
@@ -6,29 +6,19 @@ package queue
import (
"testing"
- "github.com/google/syzkaller/pkg/stats"
"github.com/stretchr/testify/assert"
)
func TestPlainQueue(t *testing.T) {
- val := stats.Create("v0", "desc0")
- pq := PlainWithStat(val)
+ pq := Plain()
req1, req2, req3 := &Request{}, &Request{}, &Request{}
pq.Submit(req1)
- assert.Equal(t, 1, val.Val())
pq.Submit(req2)
- assert.Equal(t, 2, val.Val())
-
assert.Equal(t, req1, pq.Next())
- assert.Equal(t, 1, val.Val())
-
assert.Equal(t, req2, pq.Next())
- assert.Equal(t, 0, val.Val())
-
pq.Submit(req3)
- assert.Equal(t, 1, val.Val())
assert.Equal(t, req3, pq.Next())
assert.Nil(t, pq.Next())
}
diff --git a/pkg/fuzzer/stats.go b/pkg/fuzzer/stats.go
index c860b8bb9..2129c048a 100644
--- a/pkg/fuzzer/stats.go
+++ b/pkg/fuzzer/stats.go
@@ -6,35 +6,38 @@ package fuzzer
import "github.com/google/syzkaller/pkg/stats"
type Stats struct {
- StatCandidates *stats.Val
- statNewInputs *stats.Val
- statJobs *stats.Val
- statJobsTriage *stats.Val
- statJobsSmash *stats.Val
- statJobsHints *stats.Val
- statExecTime *stats.Val
- statExecGenerate *stats.Val
- statExecFuzz *stats.Val
- statExecCandidate *stats.Val
- statExecTriage *stats.Val
- statExecMinimize *stats.Val
- statExecSmash *stats.Val
- statExecHint *stats.Val
- statExecSeed *stats.Val
- statExecCollide *stats.Val
+ statCandidates *stats.Val
+ statNewInputs *stats.Val
+ statJobs *stats.Val
+ statJobsTriage *stats.Val
+ statJobsTriageCandidate *stats.Val
+ statJobsSmash *stats.Val
+ statJobsHints *stats.Val
+ statExecTime *stats.Val
+ statExecGenerate *stats.Val
+ statExecFuzz *stats.Val
+ statExecCandidate *stats.Val
+ statExecTriage *stats.Val
+ statExecMinimize *stats.Val
+ statExecSmash *stats.Val
+ statExecHint *stats.Val
+ statExecSeed *stats.Val
+ statExecCollide *stats.Val
}
func newStats() Stats {
return Stats{
- StatCandidates: stats.Create("candidates", "Number of candidate programs in triage queue",
+ statCandidates: stats.Create("candidates", "Number of candidate programs in triage queue",
stats.Console, stats.Graph("corpus")),
statNewInputs: stats.Create("new inputs", "Potential untriaged corpus candidates",
stats.Graph("corpus")),
statJobs: stats.Create("fuzzer jobs", "Total running fuzzer jobs", stats.NoGraph),
statJobsTriage: stats.Create("triage jobs", "Running triage jobs", stats.StackedGraph("jobs")),
- statJobsSmash: stats.Create("smash jobs", "Running smash jobs", stats.StackedGraph("jobs")),
- statJobsHints: stats.Create("hints jobs", "Running hints jobs", stats.StackedGraph("jobs")),
- statExecTime: stats.Create("prog exec time", "Test program execution time (ms)", stats.Distribution{}),
+ statJobsTriageCandidate: stats.Create("candidate triage jobs", "Running candidate triage jobs",
+ stats.StackedGraph("jobs")),
+ statJobsSmash: stats.Create("smash jobs", "Running smash jobs", stats.StackedGraph("jobs")),
+ statJobsHints: stats.Create("hints jobs", "Running hints jobs", stats.StackedGraph("jobs")),
+ statExecTime: stats.Create("prog exec time", "Test program execution time (ms)", stats.Distribution{}),
statExecGenerate: stats.Create("exec gen", "Executions of generated programs", stats.Rate{},
stats.StackedGraph("exec")),
statExecFuzz: stats.Create("exec fuzz", "Executions of mutated programs",