Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions dashboard/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/google/syzkaller/pkg/hash"
"github.com/google/syzkaller/pkg/html"
"github.com/google/syzkaller/pkg/html/urlutil"
"github.com/google/syzkaller/pkg/report"
"github.com/google/syzkaller/pkg/subsystem"
"github.com/google/syzkaller/pkg/vcs"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -365,6 +366,7 @@ type uiCommit struct {
type uiBug struct {
Namespace string
Title string
ImpactScore int
NumCrashes int64
NumCrashesBad bool
BisectCause BisectStatus
Expand Down Expand Up @@ -1938,6 +1940,7 @@ func createUIBug(c context.Context, bug *Bug, state *ReportingState, managers []
uiBug := &uiBug{
Namespace: bug.Namespace,
Title: bug.displayTitle(),
ImpactScore: report.TitlesToImpact(bug.Title, bug.AltTitles...),
BisectCause: bug.BisectCause,
BisectFix: bug.BisectFix,
NumCrashes: bug.NumCrashes,
Expand Down
5 changes: 5 additions & 0 deletions dashboard/app/templates/templates.html
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ <h1><a href="/{{$.Namespace}}">syzbot</a></h1>
<th><a onclick="return sortTable(this, 'Kernel', textSort)" href="#">Kernel</a></th>
{{end}}
<th><a onclick="return sortTable(this, 'Title', textSort)" href="#">Title</a></th>
<th>
<a onclick="return sortTable(this, 'Rank 🛈', numSort)" href="#">Rank</a>
{{template "info_link" "https://github.com/google/syzkaller/blob/master/pkg/report/README.md"}}
</th>
<th><a onclick="return sortTable(this, 'Repro', reproSort)" href="#">Repro</a></th>
<th><a onclick="return sortTable(this, 'Cause bisect', textSort)" href="#">Cause bisect</a></th>
<th><a onclick="return sortTable(this, 'Fix bisect', textSort)" href="#">Fix bisect</a></th>
Expand Down Expand Up @@ -202,6 +206,7 @@ <h1><a href="/{{$.Namespace}}">syzbot</a></h1>
<span class="bug-label">{{link .Link .Name}}</span>
{{- end}}
</td>
<td class="stat">{{$b.ImpactScore}}</td>
<td class="stat">{{formatReproLevel $b.ReproLevel}}</td>
<td class="bisect_status">{{print $b.BisectCause}}</td>
<td class="bisect_status">{{print $b.BisectFix}}</td>
Expand Down
2 changes: 1 addition & 1 deletion pkg/html/pages/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function sortTable(item, colName, conv, desc = false) {

function findColumnByName(headers, colName) {
for (i = 0; i < headers.length; i++) {
if (headers[i].textContent == colName)
if (headers[i].innerText == colName)
return i;
}
return 0;
Expand Down
79 changes: 79 additions & 0 deletions pkg/report/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Bugs scoring

Until triaged we don't really know the bug impact.
But we can learn a lot from the bug title.

Syzbot scoring is based on our understanding of what bug class
looks historically more impactful.
It allows to prioritize the triaging queue.

## Heuristics

### KASAN > KMSAN > KCSAN
KASAN detected bugs are typically more dangerous than KMSAN detected bugs.
And KMSAN detected bugs are typically more dangerous than KCSAN detected bugs.

### Use-after-free write > invalid-free(double-free) > use-after-free read.

### KASAN write > KASAN read
KASAN write indicates an out-of-bounds or use-after-free write operation.
Any uncontrolled write to kernel memory is extremely dangerous
because it can corrupt data or code pointers, making it a
high-value target for exploitation leading to system compromise.
KASAN read indicates an out-of-bounds or use-after-free read.
This is generally less critical. It can crash the system (DoS)
or leak sensitive data, but it doesn't provide a direct path for an
attacker to execute their own code.

### Memory Safety bugs > DoS bugs.
This heuristic establishes a broad priority between two major classes of bugs based on their ultimate impact.

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.

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.

### Information Leaks > Denial of Service (DoS)
Kmsan infoleak and other bugs that leak kernel memory are generally
more severe than a typical DoS. These leaks can be used to bypass
security mitigations like Kernel Address Space Layout Randomization (KASLR),
which makes exploiting other vulnerabilities easier.

### Concurrency Issues > Simple DoS
Bugs like DataRace and LockdepBug can be more critical than a standard DoS.
Data races can lead to unpredictable behavior, including memory corruption,
which might be exploitable.

LockdepBug indicates potential deadlocks,
which can cause a more severe system Hang than a resource-exhaustion DoS.

### KFENCE reports are high priority
KFENCE is a lighter-weight memory safety detector compared to KASAN.
While it may have a lower performance overhead, the bugs it finds
(use-after-free, out-of-bounds) are of the same high-impact nature
as those found by KASAN.
Therefore, KFENCE detected bugs should be treated with a similar level
of urgency as KASAN reports.

### UBSAN reports require careful evaluation
The Undefined Behavior Sanitizer (UBSAN) can detect a wide range
of issues. Their severity can vary greatly:

1. A shift-out-of-bounds or array-index-out-of-bounds issue
can be very severe if it leads to memory corruption.
2. An integer-overflow can also be critical if it results in bypassing
security checks and leads to a buffer overflow.
3. Other UBSAN issues might be less critical but still indicate latent
bugs that could become problematic.

### LockdepSleeping in Atomic Context is a critical flaw
AtomicSleep is a serious bug that can lead to system-wide hangs
and instability. This is because holding a spinlock or being in
another atomic context while sleeping can cause deadlocks.

These are generally more severe than a typical DoS.

### Memory Leaks are a form of DoS
MemoryLeak bugs are a type of denial of service where the kernel
gradually runs out of memory. While generally less severe than
memory corruption, a fast memory leak that can be triggered by
an unprivileged user can be a high-impact DoS vector.
6 changes: 3 additions & 3 deletions pkg/report/crash/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const (
MemoryLeak = Type("LEAK")
MemorySafetyBUG = Type("MEMORY_SAFETY_BUG")
MemorySafetyUBSAN = Type("MEMORY_SAFETY_UBSAN")
MemorySafetyWARNING = Type("MEMORY_SAFETY_WARNING")
RefcountWARNING = Type("REFCOUNT_WARNING")
UBSAN = Type("UBSAN")
Warning = Type("WARNING")
// keep-sorted end
Expand Down Expand Up @@ -79,15 +79,15 @@ func (t Type) IsBUG() bool {
}

func (t Type) IsWarning() bool {
return t == Warning || t == MemorySafetyWARNING
return t == Warning || t == RefcountWARNING
}

func (t Type) IsBugOrWarning() bool {
return t.IsBUG() || t.IsWarning()
}

func (t Type) IsMemSafety() bool {
return t == MemorySafetyBUG || t == MemorySafetyWARNING || t == MemorySafetyUBSAN
return t == MemorySafetyBUG || t == RefcountWARNING || t == MemorySafetyUBSAN
}

func (t Type) IsMemoryLeak() bool {
Expand Down
61 changes: 61 additions & 0 deletions pkg/report/impact_score.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2025 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package report

import (
"github.com/google/syzkaller/pkg/report/crash"
)

// impactOrder represent an ordering of bug impact severity. The earlier
// entries are considered more severe.
var impactOrder = []crash.Type{
// Highest Priority (Direct Memory Corruption - Write)
crash.KASANUseAfterFreeWrite,
crash.KASANWrite,
// High Priority (Memory Corruption)
crash.KASANInvalidFree,
crash.KFENCEInvalidFree,
crash.KFENCEMemoryCorruption,
crash.KASANUseAfterFreeRead,
crash.KMSANUseAfterFreeRead,
crash.KASANRead,
crash.KFENCERead,
crash.MemorySafetyUBSAN, // array-index-out-of-bounds, at least Read.
crash.KCSANAssert,
crash.RefcountWARNING, // we had a few UAFs in the past
// Medium Priority (Infoleaks, Uninitialized Memory, Corruptions)
crash.KMSANInfoLeak,
crash.MemorySafetyBUG,
crash.KMSANUninitValue,
// Medium Priority (Concurrency and Severe Instability)
crash.KCSANDataRace,
crash.AtomicSleep, // high potential for system-wide deadlocks
crash.LockdepBug, // indicates potential deadlocks and hangs
// Lower-Medium Priority (Denial of Service and General Bugs)
crash.MemoryLeak, // a form of DoS
crash.DoS,
crash.Hang,
// Unknown types shouldn't be mentioned here. If bug goes to Unknown it means we need better parsing/processing.
// You can find them at the end of the scored list on the bug enumeration pages.
// crash.KMSANUnknown
// crash.KASANUnknown
// crash.KCSANUnknown
}

// TitlesToImpact converts a bug title(s) to an impact score.
// If several titles provided, it returns the highest score.
// A higher score indicates a more severe impact.
// -1 means unknown.
func TitlesToImpact(title string, otherTitles ...string) int {
maxImpact := -1
for _, t := range append([]string{title}, otherTitles...) {
typ := TitleToCrashType(t)
for i, t := range impactOrder {
if typ == t {
maxImpact = max(maxImpact, len(impactOrder)-i)
}
}
}
return maxImpact
}
55 changes: 55 additions & 0 deletions pkg/report/impact_score_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2025 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package report

import (
"slices"
"testing"

"github.com/google/syzkaller/pkg/report/crash"
)

const testHangTitle = "BUG: soft lockup in some function"
const testKASANInvalidFreeTitle = "KASAN: invalid-free"

func TestImpactScore(t *testing.T) {
tests := []struct {
name string
title string
expected int
}{
{
name: "unknown",
title: "KGSAN: ",
expected: -1,
},
{
name: "unknown KASAN",
title: "KASAN: unknown",
expected: -1,
},
{
name: "known Hang",
title: testHangTitle,
expected: 1, // lowest priority we can think about
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got := TitlesToImpact(test.title)
if got != test.expected {
t.Errorf("report.TitlesToImpact(%q) = %d, want %d", test.title, got, test.expected)
}
})
}
}

func TestTitlesToImpact2(t *testing.T) {
got := TitlesToImpact(testHangTitle, testKASANInvalidFreeTitle)
if got == 1 { // lowest priority we can think about (crash.Hang)
t.Errorf("report.TitlesToImpact(%q, %q) = %d, want %d",
testHangTitle, testKASANInvalidFreeTitle,
got, len(impactOrder)-slices.Index(impactOrder, crash.KASANInvalidFree))
}
}
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/157
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in sctp_wfree
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 44.461565] refcount_t: underflow; use-after-free.
[ 44.466577] ------------[ cut here ]------------
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/158
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in dev_activate
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 359.890494] refcount_t: increment on 0; use-after-free.
[ 359.914113] ------------[ cut here ]------------
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/159
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in l2tp_session_register
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 40.530345] ------------[ cut here ]------------
[ 40.535205] refcount_t: increment on 0; use-after-free.
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/405
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in cdev_get
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 1191.409330][ T6711] ------------[ cut here ]------------
[ 1191.414962][ T6711] refcount_t: increment on 0; use-after-free.
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/406
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in hci_register_dev
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 83.882482][T10363] ------------[ cut here ]------------
[ 83.894883][T10363] refcount_t: increment on 0; use-after-free.
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/408
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in input_register_device
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 116.957737] ------------[ cut here ]------------
[ 116.963070] refcount_t: increment on 0; use-after-free.
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/473
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in htc_connect_service
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 347.999844][ T4270] ------------[ cut here ]------------
[ 348.000384][ T78] steelseries_srws1 0003:1038:1410.00A7: unknown main item tag 0x0
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/622
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
TITLE: WARNING: refcount bug in memfd_secret
ALT: WARNING: refcount bug in __se_sys_memfd_secret
ALT: WARNING: refcount bug in sys_memfd_secret
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 54.834944][ T6519] ------------[ cut here ]------------
[ 54.840416][ T6519] refcount_t: addition on 0; use-after-free.
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/623
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
TITLE: WARNING: refcount bug in sys_memfd_secret
ALT: WARNING: refcount bug in __x64_sys_memfd_secret
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 90.146573][ T6540] ------------[ cut here ]------------
[ 90.172091][ T6540] refcount_t: addition on 0; use-after-free.
Expand Down
2 changes: 1 addition & 1 deletion pkg/report/testdata/linux/report/733
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TITLE: WARNING: refcount bug in hdm_disconnect
TYPE: MEMORY_SAFETY_WARNING
TYPE: REFCOUNT_WARNING

[ 82.955158][ T105] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 82.959646][ T105] usb 1-1: config 0 descriptor??
Expand Down
4 changes: 2 additions & 2 deletions pkg/report/title_to_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,11 @@ var titleToType = []struct {
includePrefixes: []string{
"WARNING: refcount bug",
},
crashType: crash.MemorySafetyWARNING,
crashType: crash.RefcountWARNING,
},
{
includePrefixes: []string{
"UBSAN: array-index",
"UBSAN: array-index-out-of-bounds",
},
crashType: crash.MemorySafetyUBSAN,
},
Expand Down