Skip to content

Commit e9ba63d

Browse files
committed
dashboard/app: sort bugs by impact
The impact score is deducted from the title. Impact is max(known_titles).
1 parent 4f67c4a commit e9ba63d

File tree

7 files changed

+208
-5
lines changed

7 files changed

+208
-5
lines changed

dashboard/app/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/google/syzkaller/pkg/hash"
2727
"github.com/google/syzkaller/pkg/html"
2828
"github.com/google/syzkaller/pkg/html/urlutil"
29+
"github.com/google/syzkaller/pkg/report"
2930
"github.com/google/syzkaller/pkg/subsystem"
3031
"github.com/google/syzkaller/pkg/vcs"
3132
"golang.org/x/sync/errgroup"
@@ -365,6 +366,7 @@ type uiCommit struct {
365366
type uiBug struct {
366367
Namespace string
367368
Title string
369+
ImpactScore int
368370
NumCrashes int64
369371
NumCrashesBad bool
370372
BisectCause BisectStatus
@@ -1938,6 +1940,7 @@ func createUIBug(c context.Context, bug *Bug, state *ReportingState, managers []
19381940
uiBug := &uiBug{
19391941
Namespace: bug.Namespace,
19401942
Title: bug.displayTitle(),
1943+
ImpactScore: report.TitlesToImpact(bug.Title, bug.AltTitles...),
19411944
BisectCause: bug.BisectCause,
19421945
BisectFix: bug.BisectFix,
19431946
NumCrashes: bug.NumCrashes,

dashboard/app/templates/templates.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ <h1><a href="/{{$.Namespace}}">syzbot</a></h1>
168168
<th><a onclick="return sortTable(this, 'Kernel', textSort)" href="#">Kernel</a></th>
169169
{{end}}
170170
<th><a onclick="return sortTable(this, 'Title', textSort)" href="#">Title</a></th>
171+
<th>
172+
<a onclick="return sortTable(this, 'Rank', numSort)" href="#">Rank</a>
173+
{{template "info_link" "https://github.com/google/syzkaller/blob/master/pkg/report/README.md"}}
174+
</th>
171175
<th><a onclick="return sortTable(this, 'Repro', reproSort)" href="#">Repro</a></th>
172176
<th><a onclick="return sortTable(this, 'Cause bisect', textSort)" href="#">Cause bisect</a></th>
173177
<th><a onclick="return sortTable(this, 'Fix bisect', textSort)" href="#">Fix bisect</a></th>
@@ -202,6 +206,7 @@ <h1><a href="/{{$.Namespace}}">syzbot</a></h1>
202206
<span class="bug-label">{{link .Link .Name}}</span>
203207
{{- end}}
204208
</td>
209+
<td class="stat">{{$b.ImpactScore}}</td>
205210
<td class="stat">{{formatReproLevel $b.ReproLevel}}</td>
206211
<td class="bisect_status">{{print $b.BisectCause}}</td>
207212
<td class="bisect_status">{{print $b.BisectFix}}</td>

pkg/report/README.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Bugs scoring
2+
3+
Until triaged we don't really know the bug impact.
4+
But we can learn a lot from the bug title.
5+
6+
Syzbot scoring is based on our understanding of what bug class
7+
looks historically more impactful.
8+
It allows to prioritize the triaging queue.
9+
10+
## Heuristics
11+
12+
### KASAN > KMSAN > KCSAN
13+
KASAN detected bugs are typically more dangerous than KMSAN detected bugs.
14+
And KMSAN detected bugs are typically more dangerous than KCSAN detected bugs.
15+
16+
### Use-after-free write > invalid-free(double-free) > use-after-free read.
17+
18+
### KASAN write > KASAN read
19+
KASAN write indicates an out-of-bounds or use-after-free write operation.
20+
Any uncontrolled write to kernel memory is extremely dangerous
21+
because it can corrupt data or code pointers, making it a
22+
high-value target for exploitation leading to system compromise.
23+
KASAN read indicates an out-of-bounds or use-after-free read.
24+
This is generally less critical. It can crash the system (DoS)
25+
or leak sensitive data, but it doesn't provide a direct path for an
26+
attacker to execute their own code.
27+
28+
### Memory Safety bugs > DoS bugs.
29+
This heuristic establishes a broad priority between two major classes of bugs based on their ultimate impact.
30+
31+
Memory Safety bugs: This category includes all the issues mentioned above—use-after-free, double-free, out-of-bounds reads/writes, etc. These are considered more severe because they represent a potential system compromise. A successful exploit can allow an attacker to escalate privileges and gain complete control over the kernel and the entire system.
32+
33+
DoS bugs (Denial of Service): This category includes bugs like kernel hangs, crashes, or resource exhaustion (e.g., memory leaks). While they are serious because they disrupt system availability, they typically do not allow an attacker to execute code or steal data. The impact is usually temporary and can be resolved by rebooting the system. They disrupt the service but don't compromise its integrity.
34+
35+
### Information Leaks > Denial of Service (DoS)
36+
Kmsan infoleak and other bugs that leak kernel memory are generally
37+
more severe than a typical DoS. These leaks can be used to bypass
38+
security mitigations like Kernel Address Space Layout Randomization (KASLR),
39+
which makes exploiting other vulnerabilities easier.
40+
41+
### Concurrency Issues > Simple DoS
42+
Bugs like DataRace and LockdepBug can be more critical than a standard DoS.
43+
Data races can lead to unpredictable behavior, including memory corruption,
44+
which might be exploitable.
45+
46+
LockdepBug indicates potential deadlocks,
47+
which can cause a more severe system Hang than a resource-exhaustion DoS.
48+
49+
### KFENCE reports are high priority
50+
KFENCE is a lighter-weight memory safety detector compared to KASAN.
51+
While it may have a lower performance overhead, the bugs it finds
52+
(use-after-free, out-of-bounds) are of the same high-impact nature
53+
as those found by KASAN.
54+
Therefore, KFENCE detected bugs should be treated with a similar level
55+
of urgency as KASAN reports.
56+
57+
### UBSAN reports require careful evaluation
58+
The Undefined Behavior Sanitizer (UBSAN) can detect a wide range
59+
of issues. Their severity can vary greatly:
60+
61+
1. A shift-out-of-bounds or array-index-out-of-bounds issue
62+
can be very severe if it leads to memory corruption.
63+
2. An integer-overflow can also be critical if it results in bypassing
64+
security checks and leads to a buffer overflow.
65+
3. Other UBSAN issues might be less critical but still indicate latent
66+
bugs that could become problematic.
67+
68+
### LockdepSleeping in Atomic Context is a critical flaw
69+
AtomicSleep is a serious bug that can lead to system-wide hangs
70+
and instability. This is because holding a spinlock or being in
71+
another atomic context while sleeping can cause deadlocks.
72+
73+
These are generally more severe than a typical DoS.
74+
75+
### Memory Leaks are a form of DoS
76+
MemoryLeak bugs are a type of denial of service where the kernel
77+
gradually runs out of memory. While generally less severe than
78+
memory corruption, a fast memory leak that can be triggered by
79+
an unprivileged user can be a high-impact DoS vector.

pkg/report/crash/types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const (
3838
MemoryLeak = Type("LEAK")
3939
MemorySafetyBUG = Type("MEMORY_SAFETY_BUG")
4040
MemorySafetyUBSAN = Type("MEMORY_SAFETY_UBSAN")
41-
MemorySafetyWARNING = Type("MEMORY_SAFETY_WARNING")
41+
RefcountWARNING = Type("REFCOUNT_WARNING")
4242
UBSAN = Type("UBSAN")
4343
Warning = Type("WARNING")
4444
// keep-sorted end
@@ -79,15 +79,15 @@ func (t Type) IsBUG() bool {
7979
}
8080

8181
func (t Type) IsWarning() bool {
82-
return t == Warning || t == MemorySafetyWARNING
82+
return t == Warning || t == RefcountWARNING
8383
}
8484

8585
func (t Type) IsBugOrWarning() bool {
8686
return t.IsBUG() || t.IsWarning()
8787
}
8888

8989
func (t Type) IsMemSafety() bool {
90-
return t == MemorySafetyBUG || t == MemorySafetyWARNING || t == MemorySafetyUBSAN
90+
return t == MemorySafetyBUG || t == RefcountWARNING || t == MemorySafetyUBSAN
9191
}
9292

9393
func (t Type) IsMemoryLeak() bool {

pkg/report/impact_score.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2025 syzkaller project authors. All rights reserved.
2+
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3+
4+
package report
5+
6+
import (
7+
"github.com/google/syzkaller/pkg/report/crash"
8+
)
9+
10+
// impactOrder represent an ordering of bug impact severity. The earlier
11+
// entries are considered more severe.
12+
var impactOrder = []crash.Type{
13+
// Highest Priority (Direct Memory Corruption - Write)
14+
crash.KASANUseAfterFreeWrite,
15+
crash.KASANWrite,
16+
// High Priority (Memory Corruption)
17+
crash.KASANInvalidFree,
18+
crash.KFENCEInvalidFree,
19+
crash.KFENCEMemoryCorruption,
20+
crash.KASANUseAfterFreeRead,
21+
crash.KMSANUseAfterFreeRead,
22+
crash.KASANRead,
23+
crash.KFENCERead,
24+
crash.MemorySafetyUBSAN, // array-index-out-of-bounds, at least Read.
25+
crash.KCSANAssert,
26+
crash.RefcountWARNING, // we had a few UAFs in the past
27+
// Medium Priority (Infoleaks, Uninitialized Memory, Corruptions)
28+
crash.KMSANInfoLeak,
29+
crash.MemorySafetyBUG,
30+
crash.KMSANUninitValue,
31+
// Medium Priority (Concurrency and Severe Instability)
32+
crash.KCSANDataRace,
33+
crash.AtomicSleep, // high potential for system-wide deadlocks
34+
crash.LockdepBug, // indicates potential deadlocks and hangs
35+
// Lower-Medium Priority (Denial of Service and General Bugs)
36+
crash.MemoryLeak, // a form of DoS
37+
crash.DoS,
38+
crash.Hang,
39+
// Unknown types shouldn't be mentioned here. If bug goes to Unknown it means we need better parsing/processing.
40+
// You can find them at the end of the scored list on the bug enumeration pages.
41+
// crash.KMSANUnknown
42+
// crash.KASANUnknown
43+
// crash.KCSANUnknown
44+
}
45+
46+
// TitlesToImpact converts a bug title(s) to an impact score.
47+
// If several titles provided, it returns the highest score.
48+
// A higher score indicates a more severe impact.
49+
// -1 means unknown.
50+
func TitlesToImpact(title string, otherTitles ...string) int {
51+
maxImpact := -1
52+
for _, t := range append([]string{title}, otherTitles...) {
53+
typ := TitleToCrashType(t)
54+
for i, t := range impactOrder {
55+
if typ == t {
56+
maxImpact = max(maxImpact, len(impactOrder)-i)
57+
}
58+
}
59+
}
60+
return maxImpact
61+
}

pkg/report/impact_score_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2025 syzkaller project authors. All rights reserved.
2+
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3+
4+
package report
5+
6+
import (
7+
"slices"
8+
"testing"
9+
10+
"github.com/google/syzkaller/pkg/report/crash"
11+
)
12+
13+
const testHangTitle = "BUG: soft lockup in some function"
14+
const testKASANInvalidFreeTitle = "KASAN: invalid-free"
15+
16+
func TestImpactScore(t *testing.T) {
17+
tests := []struct {
18+
name string
19+
title string
20+
expected int
21+
}{
22+
{
23+
name: "unknown",
24+
title: "KGSAN: ",
25+
expected: -1,
26+
},
27+
{
28+
name: "unknown KASAN",
29+
title: "KASAN: unknown",
30+
expected: -1,
31+
},
32+
{
33+
name: "known Hang",
34+
title: testHangTitle,
35+
expected: 1, // lowest priority we can think about
36+
},
37+
}
38+
for _, test := range tests {
39+
t.Run(test.name, func(t *testing.T) {
40+
got := TitlesToImpact(test.title)
41+
if got != test.expected {
42+
t.Errorf("report.TitlesToImpact(%q) = %d, want %d", test.title, got, test.expected)
43+
}
44+
})
45+
}
46+
}
47+
48+
func TestTitlesToImpact2(t *testing.T) {
49+
got := TitlesToImpact(testHangTitle, testKASANInvalidFreeTitle)
50+
if got == 1 { // lowest priority we can think about (crash.Hang)
51+
t.Errorf("report.TitlesToImpact(%q, %q) = %d, want %d",
52+
testHangTitle, testKASANInvalidFreeTitle,
53+
got, len(impactOrder)-slices.Index(impactOrder, crash.KASANInvalidFree))
54+
}
55+
}

pkg/report/title_to_type.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,11 @@ var titleToType = []struct {
146146
includePrefixes: []string{
147147
"WARNING: refcount bug",
148148
},
149-
crashType: crash.MemorySafetyWARNING,
149+
crashType: crash.RefcountWARNING,
150150
},
151151
{
152152
includePrefixes: []string{
153-
"UBSAN: array-index",
153+
"UBSAN: array-index-out-of-bounds",
154154
},
155155
crashType: crash.MemorySafetyUBSAN,
156156
},

0 commit comments

Comments
 (0)