aboutsummaryrefslogtreecommitdiffstats
path: root/syz-manager
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2024-07-11 12:24:08 +0200
committerAleksandr Nogikh <nogikh@google.com>2024-07-22 09:10:35 +0000
commitedb73b3601f18f3fe4bfc4dbb4f2aaf2b4b764c3 (patch)
tree620b5538c9c019191b781de2166e555765bf9bb7 /syz-manager
parentcc2c251549aa339bba0fefed38dba52a1cde5e3a (diff)
syz-manager: prioritize manual repro requests
Explicitly enforce the prioritization rules. Add a test to verify them.
Diffstat (limited to 'syz-manager')
-rw-r--r--syz-manager/manager.go2
-rw-r--r--syz-manager/repro.go25
-rw-r--r--syz-manager/repro_test.go38
3 files changed, 62 insertions, 3 deletions
diff --git a/syz-manager/manager.go b/syz-manager/manager.go
index 105117ef0..b7c69558a 100644
--- a/syz-manager/manager.go
+++ b/syz-manager/manager.go
@@ -155,6 +155,7 @@ type Crash struct {
instanceName string
fromHub bool // this crash was created based on a repro from syz-hub
fromDashboard bool // .. or from dashboard
+ manual bool
*report.Report
}
@@ -1614,6 +1615,7 @@ func (mgr *Manager) dashboardReproTasks() {
if len(resp.CrashLog) > 0 {
mgr.externalReproQueue <- &Crash{
fromDashboard: true,
+ manual: resp.Type == dashapi.ManualLog,
Report: &report.Report{
Title: resp.Title,
Output: resp.CrashLog,
diff --git a/syz-manager/repro.go b/syz-manager/repro.go
index 8a4e75c27..3e2b2a315 100644
--- a/syz-manager/repro.go
+++ b/syz-manager/repro.go
@@ -127,14 +127,33 @@ func (m *reproManager) popCrash() *Crash {
m.mu.Lock()
defer m.mu.Unlock()
+ newBetter := func(base, new *Crash) bool {
+ // First, serve manual requests.
+ if new.manual != base.manual {
+ return new.manual
+ }
+ // Then, deprioritize hub reproducers.
+ if new.fromHub != base.fromHub {
+ return !new.fromHub
+ }
+ return false
+ }
+
+ idx := -1
for i, crash := range m.queue {
if m.reproducing[crash.FullTitle()] {
continue
}
- m.queue = slices.Delete(m.queue, i, i+1)
- return crash
+ if idx == -1 || newBetter(m.queue[idx], m.queue[i]) {
+ idx = i
+ }
+ }
+ if idx == -1 {
+ return nil
}
- return nil
+ crash := m.queue[idx]
+ m.queue = slices.Delete(m.queue, idx, idx+1)
+ return crash
}
func (m *reproManager) Loop(ctx context.Context) {
diff --git a/syz-manager/repro_test.go b/syz-manager/repro_test.go
index 79b482d36..8042c7042 100644
--- a/syz-manager/repro_test.go
+++ b/syz-manager/repro_test.go
@@ -67,6 +67,44 @@ func TestReproManager(t *testing.T) {
t.Fatal("reserved VMs must have dropped to 0")
}
+func TestReproOrder(t *testing.T) {
+ mock := &reproMgrMock{
+ run: make(chan runCallback),
+ }
+ obj := newReproManager(mock, 3, false)
+
+ // The right order is A B C.
+ crashes := []*Crash{
+ {
+ Report: &report.Report{Title: "A"},
+ fromDashboard: true,
+ manual: true,
+ },
+ {
+ Report: &report.Report{Title: "B"},
+ fromDashboard: true,
+ },
+ {
+ Report: &report.Report{Title: "C"},
+ fromHub: true,
+ },
+ }
+
+ obj.Enqueue(crashes[2])
+ obj.Enqueue(crashes[1])
+ obj.Enqueue(crashes[0])
+ assert.Equal(t, crashes[0], obj.popCrash())
+ assert.Equal(t, crashes[1], obj.popCrash())
+ assert.Equal(t, crashes[2], obj.popCrash())
+
+ obj.Enqueue(crashes[1])
+ obj.Enqueue(crashes[0])
+ obj.Enqueue(crashes[2])
+ assert.Equal(t, crashes[0], obj.popCrash())
+ assert.Equal(t, crashes[1], obj.popCrash())
+ assert.Equal(t, crashes[2], obj.popCrash())
+}
+
type reproMgrMock struct {
reserved atomic.Int64
run chan runCallback