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
27 changes: 22 additions & 5 deletions pkg/bisect/bisect.go
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,11 @@ func mostFrequentReports(reports []*report.Report) (*report.Report, []crash.Type
// bisecting this kind of a bug.
continue
}
if info.t == crash.LostConnection && len(perType) > 1 {
// This crash type is much more often unrelated than not.
// Take it only if it's the only crash type.
continue
}
// Take further crash types until we have considered 2/3 of all crashes, but
// no more than 3.
needTaken := (crashes + 2) * 2 / 3
Expand All @@ -1009,12 +1014,24 @@ func mostFrequentReports(reports []*report.Report) (*report.Report, []crash.Type
func (env *env) isTransientError(rep *report.Report) bool {
// If we're not chasing a SYZFATAL error, ignore them.
// Otherwise it indicates some transient problem of the tested kernel revision.
hadSyzFailure := false
for _, t := range env.reportTypes {
hadSyzFailure = hadSyzFailure || t == crash.SyzFailure
if rep.Type == crash.SyzFailure {
hadSyzFailure := false
for _, t := range env.reportTypes {
hadSyzFailure = hadSyzFailure || t == crash.SyzFailure
}
return len(env.reportTypes) > 0 && !hadSyzFailure
}
// Lost connection is a frequent source of flaky results.
// Ignore if it is was not in the canonical crash types set.
if rep.Type == crash.LostConnection {
hadLostConnection := false
for _, t := range env.reportTypes {
hadLostConnection = hadLostConnection || t == crash.LostConnection
}
return len(env.reportTypes) > 0 && !hadLostConnection
}
return rep.Type == crash.SyzFailure &&
len(env.reportTypes) > 0 && !hadSyzFailure
// All other errors are okay.
return false
}

func (env *env) saveDebugFile(hash string, idx int, data []byte) {
Expand Down
70 changes: 59 additions & 11 deletions pkg/bisect/bisect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,27 @@ func (env *testEnv) Test(numVMs int, reproSyz, reproOpts, reproC []byte) ([]inst
}
return ret, nil
}
ret = make([]instance.EnvTestResult, numVMs-1)
ret = make([]instance.EnvTestResult, numVMs)
if env.test.injectSyzFailure {
ret = append(ret, instance.EnvTestResult{
Error: &instance.TestError{
ret[0] = instance.EnvTestResult{
Error: &instance.CrashError{
Report: &report.Report{
Title: "SYZFATAL: test",
Type: crash.SyzFailure,
},
},
})
} else {
ret = append(ret, instance.EnvTestResult{})
}
} else if env.test.injectLostConnection {
for i := 0; i < numVMs/3; i++ {
ret[i] = instance.EnvTestResult{
Error: &instance.CrashError{
Report: &report.Report{
Title: "lost connection to test machine",
Type: crash.LostConnection,
},
},
}
}
}
return ret, nil
}
Expand Down Expand Up @@ -312,11 +321,12 @@ type BisectionTest struct {
expectErr bool
expectErrType any
// Expect res.Report != nil.
expectRep bool
noopChange bool
isRelease bool
flaky bool
injectSyzFailure bool
expectRep bool
noopChange bool
isRelease bool
flaky bool
injectSyzFailure bool
injectLostConnection bool
// Expected number of returned commits for inconclusive bisection.
commitLen int
// For cause bisection: Oldest commit returned by bisection.
Expand Down Expand Up @@ -496,6 +506,16 @@ var bisectionTests = []BisectionTest{
fixCommit: "500",
isRelease: true,
},
// Tests that bisection returns the correct fix commit despite `lost connection to test machine`.
{
name: "fix-finds-fix-despite-lost-connection",
fix: true,
startCommit: 400,
injectLostConnection: true,
commitLen: 1,
fixCommit: "500",
isRelease: true,
},
// Tests that bisection returns the correct fix commit in case of SYZFATAL.
{
name: "fix-finds-fix-for-syzfatal",
Expand Down Expand Up @@ -958,6 +978,34 @@ func TestMostFrequentReport(t *testing.T) {
report: "A",
other: true,
},
{
name: "do not take lost connection",
reports: []*report.Report{
{Title: "A", Type: crash.LostConnection},
{Title: "B", Type: crash.Warning},
{Title: "C", Type: crash.LostConnection},
{Title: "D", Type: crash.Warning},
{Title: "E", Type: crash.LostConnection},
{Title: "F", Type: crash.Warning},
},
types: []crash.Type{crash.Warning},
report: "B",
other: true,
},
{
name: "only lost connection",
reports: []*report.Report{
{Title: "A", Type: crash.LostConnection},
{Title: "B", Type: crash.LostConnection},
{Title: "C", Type: crash.LostConnection},
{Title: "D", Type: crash.LostConnection},
{Title: "E", Type: crash.LostConnection},
{Title: "F", Type: crash.LostConnection},
},
types: []crash.Type{crash.LostConnection},
report: "A",
other: false,
},
}
for _, test := range tests {
test := test
Expand Down
1 change: 1 addition & 0 deletions pkg/report/crash/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
AtomicSleep = Type("ATOMIC_SLEEP")
KMSAN = Type("KMSAN")
SyzFailure = Type("SYZ_FAILURE")
LostConnection = Type("LOST_CONNECTION")
)

func (t Type) String() string {
Expand Down
6 changes: 6 additions & 0 deletions vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/pkg/stat"
"github.com/google/syzkaller/sys/targets"
"github.com/google/syzkaller/vm/dispatcher"
Expand Down Expand Up @@ -498,10 +499,15 @@ func (mon *monitor) createReport(defaultError string) *report.Report {
if defaultError == "" {
return nil
}
typ := crash.UnknownType
if defaultError == lostConnectionCrash {
typ = crash.LostConnection
}
return &report.Report{
Title: defaultError,
Output: mon.output,
Suppressed: report.IsSuppressed(mon.reporter, mon.output),
Type: typ,
}
}
start := rep.StartPos - mon.beforeContext
Expand Down
8 changes: 8 additions & 0 deletions vm/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/report"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/sys/targets"
"github.com/google/syzkaller/vm/vmimpl"
)
Expand Down Expand Up @@ -115,6 +116,7 @@ var tests = []*Test{
},
Report: &report.Report{
Title: lostConnectionCrash,
Type: crash.LostConnection,
},
},
{
Expand All @@ -135,6 +137,7 @@ var tests = []*Test{
Output: []byte(
"DIAGNOSE\n",
),
Type: crash.LostConnection,
},
},
{
Expand All @@ -150,6 +153,7 @@ var tests = []*Test{
"VM DIAGNOSIS:\n" +
"DIAGNOSE\n",
),
Type: crash.LostConnection,
},
},
{
Expand Down Expand Up @@ -237,6 +241,7 @@ var tests = []*Test{
},
Report: &report.Report{
Title: lostConnectionCrash,
Type: crash.LostConnection,
},
},
{
Expand Down Expand Up @@ -417,6 +422,9 @@ func testMonitorExecution(t *testing.T, test *Test) {
if test.Report.Output != nil && !bytes.Equal(test.Report.Output, rep.Output) {
t.Fatalf("want output:\n%s\n\ngot output:\n%s", test.Report.Output, rep.Output)
}
if test.Report.Type != rep.Type {
t.Fatalf("want type %q, got type %q", test.Report.Type, rep.Type)
}
}

func TestVMType(t *testing.T) {
Expand Down