pkg/report: detect syzkaller panics in lost connection bugs

Some syzkaller panics happen due to memory corruptions,
but it still would be useful at least to get some visibility into these crashes.
On some OSes we actualy already detect them as they have "panic:" oops pattern,
but not e.g. on linux.

Fixes #318
This commit is contained in:
Dmitry Vyukov 2019-11-06 11:39:02 +01:00
parent 424cf6e8a1
commit da505f84d3
14 changed files with 163 additions and 63 deletions

View File

@ -133,7 +133,7 @@ var akarosStackParams = &stackParams{
}, },
} }
var akarosOopses = []*oops{ var akarosOopses = append([]*oops{
{ {
[]byte("kernel panic"), []byte("kernel panic"),
[]oopsFormat{ []oopsFormat{
@ -188,4 +188,4 @@ var akarosOopses = []*oops{
}, },
[]*regexp.Regexp{}, []*regexp.Regexp{},
}, },
} }, commonOopses...)

View File

@ -73,7 +73,7 @@ func (ctx *freebsd) Symbolize(rep *Report) error {
var freebsdStackParams = &stackParams{} var freebsdStackParams = &stackParams{}
var freebsdOopses = []*oops{ var freebsdOopses = append([]*oops{
{ {
[]byte("Fatal trap"), []byte("Fatal trap"),
[]oopsFormat{ []oopsFormat{
@ -123,4 +123,4 @@ var freebsdOopses = []*oops{
}, },
[]*regexp.Regexp{}, []*regexp.Regexp{},
}, },
} }, commonOopses...)

View File

@ -185,7 +185,7 @@ var zirconStackParams = &stackParams{
}, },
} }
var zirconOopses = []*oops{ var zirconOopses = append([]*oops{
{ {
[]byte("ZIRCON KERNEL PANIC"), []byte("ZIRCON KERNEL PANIC"),
[]oopsFormat{ []oopsFormat{
@ -316,17 +316,4 @@ var zirconOopses = []*oops{
compile("<== fatal exception: process .+?syz.+?\\["), compile("<== fatal exception: process .+?syz.+?\\["),
}, },
}, },
{ }, commonOopses...)
// Panics in Go services.
[]byte("panic: "),
[]oopsFormat{
{
title: compile("panic: .*"),
report: compile("panic: (.*)(?:.*\\n)+?.* goroutine"),
fmt: "panic: %[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
}

View File

@ -95,18 +95,7 @@ var gvisorTitleReplacement = []replacement{
}, },
} }
var gvisorOopses = []*oops{ var gvisorOopses = append([]*oops{
{
[]byte("panic:"),
[]oopsFormat{
{
title: compile("panic:(.*)"),
fmt: "panic:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{ {
[]byte("Panic:"), []byte("Panic:"),
[]oopsFormat{ []oopsFormat{
@ -129,17 +118,6 @@ var gvisorOopses = []*oops{
}, },
[]*regexp.Regexp{}, []*regexp.Regexp{},
}, },
{
[]byte("runtime error:"),
[]oopsFormat{
{
title: compile("runtime error:(.*)"),
fmt: "runtime error:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
{ {
[]byte("SIGSEGV:"), []byte("SIGSEGV:"),
[]oopsFormat{ []oopsFormat{
@ -197,4 +175,4 @@ var gvisorOopses = []*oops{
}, },
[]*regexp.Regexp{}, []*regexp.Regexp{},
}, },
} }, commonOopses...)

View File

@ -853,7 +853,7 @@ func warningStackFmt(skip ...string) *stackFmt {
} }
} }
var linuxOopses = []*oops{ var linuxOopses = append([]*oops{
{ {
[]byte("BUG:"), []byte("BUG:"),
[]oopsFormat{ []oopsFormat{
@ -1584,4 +1584,4 @@ var linuxOopses = []*oops{
}, },
[]*regexp.Regexp{}, []*regexp.Regexp{},
}, },
} }, commonOopses...)

View File

@ -145,7 +145,7 @@ func (ctx *netbsd) symbolizeLine(symbFunc func(bin string, pc uint64) ([]symboli
} }
// nolint: lll // nolint: lll
var netbsdOopses = []*oops{ var netbsdOopses = append([]*oops{
{ {
[]byte("fault in supervisor mode"), []byte("fault in supervisor mode"),
[]oopsFormat{ []oopsFormat{
@ -188,4 +188,4 @@ var netbsdOopses = []*oops{
}, },
[]*regexp.Regexp{}, []*regexp.Regexp{},
}, },
} }, commonOopses...)

View File

@ -136,7 +136,7 @@ func (ctx *openbsd) symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbol
return symbolized return symbolized
} }
var openbsdOopses = []*oops{ var openbsdOopses = append([]*oops{
{ {
[]byte("cleaned vnode"), []byte("cleaned vnode"),
[]oopsFormat{ []oopsFormat{
@ -235,4 +235,4 @@ var openbsdOopses = []*oops{
compile("reorder_kernel"), compile("reorder_kernel"),
}, },
}, },
} }, commonOopses...)

View File

@ -593,3 +593,19 @@ var (
filenameRe = regexp.MustCompile(`[a-zA-Z0-9_\-\./]*[a-zA-Z0-9_\-]+\.(c|h):[0-9]+`) filenameRe = regexp.MustCompile(`[a-zA-Z0-9_\-\./]*[a-zA-Z0-9_\-]+\.(c|h):[0-9]+`)
reportFrameRe = regexp.MustCompile(`.* in ([a-zA-Z0-9_]+)`) reportFrameRe = regexp.MustCompile(`.* in ([a-zA-Z0-9_]+)`)
) )
// These are produced by syzkaller itself.
// But also catches crashes in Go programs in gvisor/fuchsia.
var commonOopses = []*oops{
{
[]byte("panic:"),
[]oopsFormat{
{
title: compile("panic:(.*)"),
fmt: "panic:%[1]v",
noStackTrace: true,
},
},
[]*regexp.Regexp{},
},
}

View File

@ -303,15 +303,9 @@ func testGuiltyFile(t *testing.T, reporter Reporter, fn string) {
} }
func forEachFile(t *testing.T, dir string, fn func(t *testing.T, reporter Reporter, fn string)) { func forEachFile(t *testing.T, dir string, fn func(t *testing.T, reporter Reporter, fn string)) {
testFilenameRe := regexp.MustCompile("^[0-9]+$")
for os := range ctors { for os := range ctors {
path := filepath.Join("testdata", os, dir) if os == "windows" {
if !osutil.IsExist(path) { continue // not implemented
continue
}
files, err := ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
} }
cfg := &mgrconfig.Config{ cfg := &mgrconfig.Config{
TargetOS: os, TargetOS: os,
@ -321,17 +315,37 @@ func forEachFile(t *testing.T, dir string, fn func(t *testing.T, reporter Report
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
for _, file := range files { for _, file := range readDir(t, filepath.Join("testdata", os, dir)) {
if !testFilenameRe.MatchString(file.Name()) { t.Run(fmt.Sprintf("%v/%v", os, filepath.Base(file)), func(t *testing.T) {
continue fn(t, reporter, file)
} })
t.Run(fmt.Sprintf("%v/%v", os, file.Name()), func(t *testing.T) { }
fn(t, reporter, filepath.Join(path, file.Name())) for _, file := range readDir(t, filepath.Join("testdata", "all", dir)) {
t.Run(fmt.Sprintf("%v/all/%v", os, filepath.Base(file)), func(t *testing.T) {
fn(t, reporter, file)
}) })
} }
} }
} }
func readDir(t *testing.T, dir string) (files []string) {
if !osutil.IsExist(dir) {
return nil
}
entries, err := ioutil.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
testFilenameRe := regexp.MustCompile("^[0-9]+$")
for _, ent := range entries {
if !testFilenameRe.MatchString(ent.Name()) {
continue
}
files = append(files, filepath.Join(dir, ent.Name()))
}
return
}
func TestReplace(t *testing.T) { func TestReplace(t *testing.T) {
tests := []struct { tests := []struct {
where string where string

19
pkg/report/testdata/all/report/0 vendored Normal file
View File

@ -0,0 +1,19 @@
TITLE: panic: bad arg kind
panic: bad arg kind
goroutine 25 [running]:
github.com/google/syzkaller/prog.clone(0x0, 0x0, 0xc003ab9e38, 0xc001037040, 0x10)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/clone.go:75 +0x8b8
github.com/google/syzkaller/prog.clone(0x97ca80, 0xc001d3f650, 0xc003ab9e38, 0xc00184bf70, 0x30)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/clone.go:53 +0x17c
github.com/google/syzkaller/prog.clone(0x97ca80, 0xc001d3f680, 0xc003ab9e38, 0xc003ab9ec8, 0x30)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/clone.go:53 +0x17c
github.com/google/syzkaller/prog.clone(0x97cac0, 0xc001d3f6b0, 0xc003ab9e38, 0x97cb00, 0xc0022c7940)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/clone.go:40 +0x570
github.com/google/syzkaller/prog.(*Prog).Clone(0xc001d8d100, 0xc002fdb470)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/clone.go:20 +0x270
main.(*Proc).loop(0xc002fc86c0)
/syzkaller/gopath/src/github.com/google/syzkaller/syz-fuzzer/proc.go:98 +0x3cb
created by main.main
/syzkaller/gopath/src/github.com/google/syzkaller/syz-fuzzer/fuzzer.go:258 +0x111b

25
pkg/report/testdata/all/report/1 vendored Normal file
View File

@ -0,0 +1,25 @@
TITLE: panic: no result
panic: no result
goroutine 36 [running]:
github.com/google/syzkaller/prog.(*ResultArg).serialize(0xc005120640, 0xc005177420)
/home/ghani/go/src/github.com/google/syzkaller/prog/encoding.go:172 +0x3a7
github.com/google/syzkaller/prog.(*serializer).arg(0xc005177420, 0x9f5ec0, 0xc005120640)
/home/ghani/go/src/github.com/google/syzkaller/prog/encoding.go:80 +0x40
github.com/google/syzkaller/prog.(*serializer).call(0xc005177420, 0xc005120600)
/home/ghani/go/src/github.com/google/syzkaller/prog/encoding.go:70 +0x1d6
github.com/google/syzkaller/prog.(*Prog).Serialize(0xc0051205c0, 0xc00516fb30, 0x717465, 0xc00516fb38)
/home/ghani/go/src/github.com/google/syzkaller/prog/encoding.go:35 +0xc8
main.(*Proc).logProgram(0xc000101fc0, 0xc0000240e0, 0xc0051205c0)
/home/ghani/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:316 +0x59
main.(*Proc).executeRaw(0xc000101fc0, 0xc0000240e0, 0xc0051205c0, 0x5, 0x0)
/home/ghani/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:293 +0xd4
main.(*Proc).execute(0xc000101fc0, 0xc0000240e0, 0xc0051205c0, 0x0, 0x5, 0x1)
/home/ghani/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:259 +0x67
main.(*Proc).smashInput(0xc000101fc0, 0xc004f79f50)
/home/ghani/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:223 +0x1d4
main.(*Proc).loop(0xc000101fc0)
/home/ghani/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:84 +0x12f
created by main.main
/home/ghani/go/src/github.com/google/syzkaller/syz-fuzzer/fuzzer.go:242 +0x1011

22
pkg/report/testdata/all/report/2 vendored Normal file
View File

@ -0,0 +1,22 @@
TITLE: panic: executor 2: failed: event already set (errno 0)
panic: executor 2: failed: event already set (errno 0)
child failed (errno 2)
loop failed (errno 0)
goroutine 16 [running]:
main.(*Proc).executeRaw(0x442002b480, 0x44200cafa0, 0x44280cbee0, 0x4, 0x0, 0x0, 0x0)
/home/jbtheou/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:271 +0x39c
main.(*Proc).execute(0x442002b480, 0x44200cafa0, 0x44280cbee0, 0x0, 0x4, 0x442625ce60, 0x1, 0x2a7260)
/home/jbtheou/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:231 +0x40
main.(*Proc).triageInput.func1(0x44280cbee0, 0x4, 0x1)
/home/jbtheou/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:145 +0x88
github.com/google/syzkaller/prog.Minimize(0x4423334b60, 0x6, 0x200, 0x4424751de8, 0x442b100e10, 0x7)
/home/jbtheou/go/src/github.com/google/syzkaller/prog/minimization.go:43 +0x10c
main.(*Proc).triageInput(0x442002b480, 0x4423531ec0)
/home/jbtheou/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:142 +0x658
main.(*Proc).loop(0x442002b480)
/home/jbtheou/go/src/github.com/google/syzkaller/syz-fuzzer/proc.go:72 +0xe4
created by main.main
/home/jbtheou/go/src/github.com/google/syzkaller/syz-fuzzer/fuzzer.go:294 +0xc90

17
pkg/report/testdata/all/report/3 vendored Normal file
View File

@ -0,0 +1,17 @@
TITLE: panic: first open arg is not a pointer to string const
panic: first open arg is not a pointer to string const
goroutine 1 [running]:
github.com/google/syzkaller/pkg/host.extractStringConst(0x6858e0, 0xecfde0, 0x0, 0x0, 0xffffffffffffffff)
/home/thesis/gopath/src/github.com/google/syzkaller/pkg/host/host_linux.go:167 +0xdc
github.com/google/syzkaller/pkg/host.isSupportedOpenAt(0xb413e0, 0x7)
/home/thesis/gopath/src/github.com/google/syzkaller/pkg/host/host_linux.go:153 +0x3c
github.com/google/syzkaller/pkg/host.isSupported(0x4421a14000, 0x53eadf, 0x7ffe00, 0xb413e0, 0x4420081f00)
/home/thesis/gopath/src/github.com/google/syzkaller/pkg/host/host_linux.go:52 +0x178
github.com/google/syzkaller/pkg/host.DetectSupportedSyscalls(0x44201d4480, 0x4420081f80, 0xb4df80, 0x442190701e)
/home/thesis/gopath/src/github.com/google/syzkaller/pkg/host/host_linux.go:34 +0xd0
main.buildCallList(0x44201d4480, 0x44218ec000, 0x1904, 0xf)
/home/thesis/gopath/src/github.com/google/syzkaller/syz-fuzzer/fuzzer.go:459 +0xbc
main.main()
/home/thesis/gopath/src/github.com/google/syzkaller/syz-fuzzer/fuzzer.go:155 +0x44c

22
pkg/report/testdata/all/report/4 vendored Normal file
View File

@ -0,0 +1,22 @@
TITLE: panic: runtime error: invalid memory address or nil pointer dereference
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x88 pc=0x7a0381]
goroutine 24 [running]:
github.com/google/syzkaller/prog.chooseCall.func1(0x9a6240, 0xc00306eb40, 0xc003ac0b60)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/mutation.go:198 +0x51
github.com/google/syzkaller/prog.foreachArgImpl(0x9a6240, 0xc00306eb40, 0xc003035fc8, 0x0, 0x0, 0x0, 0xc002effd60)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/analysis.go:125 +0xbe
github.com/google/syzkaller/prog.ForeachArg(0xc003035fc0, 0xc002effd60)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/analysis.go:120 +0x9e
github.com/google/syzkaller/prog.chooseCall(0xc002fc8080, 0xc003ac9420, 0xc002c616b0, 0xc002effdc0)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/mutation.go:197 +0x10d
github.com/google/syzkaller/prog.(*mutator).mutateArg(0xc002effec0, 0xa)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/mutation.go:161 +0x67
github.com/google/syzkaller/prog.(*Prog).Mutate(0xc002fc8080, 0x9a0ac0, 0xc002c0d560, 0x1e, 0xc002e96980, 0xc003022000, 0x1e78, 0x2400)
/syzkaller/gopath/src/github.com/google/syzkaller/prog/mutation.go:44 +0x2da
main.(*Proc).loop(0xc002fe2500)
/syzkaller/gopath/src/github.com/google/syzkaller/syz-fuzzer/proc.go:99 +0x434
created by main.main
/syzkaller/gopath/src/github.com/google/syzkaller/syz-fuzzer/fuzzer.go:259 +0x114c