mirror of
https://github.com/reactos/syzkaller.git
synced 2024-10-07 17:13:26 +00:00
pkg/report: support freebsd
This commit is contained in:
parent
85c802e4cf
commit
6368c469a5
@ -4,6 +4,8 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/google/syzkaller/pkg/symbolizer"
|
||||
@ -28,25 +30,88 @@ func ctorFreebsd(kernelSrc, kernelObj string, symbols map[string][]symbolizer.Sy
|
||||
}
|
||||
|
||||
func (ctx *freebsd) ContainsCrash(output []byte) bool {
|
||||
panic("not implemented")
|
||||
return containsCrash(output, freebsdOopses, ctx.ignores)
|
||||
}
|
||||
|
||||
func (ctx *freebsd) Parse(output []byte) (desc string, text []byte, start int, end int) {
|
||||
panic("not implemented")
|
||||
var oops *oops
|
||||
for pos := 0; pos < len(output); {
|
||||
next := bytes.IndexByte(output[pos:], '\n')
|
||||
if next != -1 {
|
||||
next += pos
|
||||
} else {
|
||||
next = len(output)
|
||||
}
|
||||
for _, oops1 := range freebsdOopses {
|
||||
match := matchOops(output[pos:next], oops1, ctx.ignores)
|
||||
if match == -1 {
|
||||
continue
|
||||
}
|
||||
if oops == nil {
|
||||
oops = oops1
|
||||
start = pos
|
||||
desc = string(output[pos+match : next])
|
||||
}
|
||||
end = next
|
||||
}
|
||||
// Console output is indistinguishable from fuzzer output,
|
||||
// so we just collect everything after the oops.
|
||||
if oops != nil {
|
||||
lineEnd := next
|
||||
if lineEnd != 0 && output[lineEnd-1] == '\r' {
|
||||
lineEnd--
|
||||
}
|
||||
text = append(text, output[pos:lineEnd]...)
|
||||
text = append(text, '\n')
|
||||
}
|
||||
pos = next + 1
|
||||
}
|
||||
if oops == nil {
|
||||
return
|
||||
}
|
||||
desc = extractDescription(output[start:], oops)
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx *freebsd) Symbolize(text []byte) ([]byte, error) {
|
||||
panic("not implemented")
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (ctx *freebsd) ExtractConsoleOutput(output []byte) (result []byte) {
|
||||
panic("not implemented")
|
||||
return output
|
||||
}
|
||||
|
||||
func (ctx *freebsd) ExtractGuiltyFile(report []byte) string {
|
||||
panic("not implemented")
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ctx *freebsd) GetMaintainers(file string) ([]string, error) {
|
||||
panic("not implemented")
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
var freebsdOopses = []*oops{
|
||||
&oops{
|
||||
[]byte("Fatal trap"),
|
||||
[]oopsFormat{
|
||||
{
|
||||
compile("Fatal trap (.+?)\\r?\\n(?:.*\\n)+?" +
|
||||
"KDB: stack backtrace:\\r?\\n" +
|
||||
"(?:#[0-9]+ {{ADDR}} at (?:kdb_backtrace|vpanic|panic|trap_fatal|" +
|
||||
"trap_pfault|trap|calltrap|m_copydata|__rw_wlock_hard)" +
|
||||
"\\+{{ADDR}}\\r?\\n)*#[0-9]+ {{ADDR}} at {{FUNC}}{{ADDR}}"),
|
||||
"Fatal trap %[1]v in %[2]v",
|
||||
},
|
||||
},
|
||||
[]*regexp.Regexp{},
|
||||
},
|
||||
&oops{
|
||||
[]byte("panic:"),
|
||||
[]oopsFormat{
|
||||
{
|
||||
compile("panic: ffs_write: type {{ADDR}} [0-9]+ \\([0-9]+,[0-9]+\\)"),
|
||||
"panic: ffs_write: type ADDR X (Y,Z)",
|
||||
},
|
||||
},
|
||||
[]*regexp.Regexp{},
|
||||
},
|
||||
}
|
||||
|
126
pkg/report/freebsd_test.go
Normal file
126
pkg/report/freebsd_test.go
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright 2017 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 (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFreebsdParse(t *testing.T) {
|
||||
testParse(t, "freebsd", freebsdTests)
|
||||
}
|
||||
|
||||
var freebsdTests = map[string]string{
|
||||
`
|
||||
Fatal trap 12: page fault while in kernel mode
|
||||
cpuid = 0; apic id = 00
|
||||
fault virtual address = 0xffffffff12852143
|
||||
fault code = supervisor read data, page not present
|
||||
instruction pointer = 0x20:0xffffffff8102fe62
|
||||
stack pointer = 0x28:0xfffffe009524a960
|
||||
frame pointer = 0x28:0xfffffe009524a990
|
||||
code segment = base 0x0, limit 0xfffff, type 0x1b
|
||||
= DPL 0, pres 1, long 1, def32 0, gran 1
|
||||
processor eflags = interrupt enabled, resume, IOPL = 0
|
||||
current process = 3094 (syz-executor0)
|
||||
trap number = 12
|
||||
panic: page fault
|
||||
cpuid = 0
|
||||
KDB: stack backtrace:
|
||||
#0 0xffffffff80aada97 at kdb_backtrace+0x67
|
||||
#1 0xffffffff80a6bb76 at vpanic+0x186
|
||||
#2 0xffffffff80a6b9e3 at panic+0x43
|
||||
#3 0xffffffff80edf832 at trap_fatal+0x322
|
||||
#4 0xffffffff80edf889 at trap_pfault+0x49
|
||||
#5 0xffffffff80edf0c6 at trap+0x286
|
||||
#6 0xffffffff80ec3641 at calltrap+0x8
|
||||
#7 0xffffffff810302fc at atrtc_settime+0xc
|
||||
#8 0xffffffff80ab7361 at resettodr+0xf1
|
||||
#9 0xffffffff80a7fcc6 at settime+0x156
|
||||
#10 0xffffffff80a7fae5 at sys_clock_settime+0x85
|
||||
#11 0xffffffff80ee0394 at amd64_syscall+0x6c4
|
||||
#12 0xffffffff80ec392b at Xfast_syscall+0xfb
|
||||
`: `Fatal trap 12: page fault while in kernel mode in atrtc_settime`,
|
||||
|
||||
`
|
||||
Fatal trap 12: page fault while in kernel mode
|
||||
cpuid = 3; apic id = 03
|
||||
fault virtual address = 0xfffff7ffb48e19a8
|
||||
fault code = supervisor read data, page not present
|
||||
instruction pointer = 0x20:0xffffffff80edd52a
|
||||
stack pointer = 0x28:0xfffffe009524a7a0
|
||||
frame pointer = 0x28:0xfffffe009524a7a0
|
||||
code segment = base 0x0, limit 0xfffff, type 0x1b
|
||||
= DPL 0, pres 1, long 1, def32 0, gran 1
|
||||
processor eflags = interrupt enabled, resume, IOPL = 0
|
||||
current process = 40394 (syz-executor1)
|
||||
trap number = 12
|
||||
panic: page fault
|
||||
cpuid = 3
|
||||
KDB: stack backtrace:
|
||||
#0 0xffffffff80aada97 at kdb_backtrace+0x67
|
||||
#1 0xffffffff80a6bb76 at vpanic+0x186
|
||||
#2 0xffffffff80a6b9e3 at panic+0x43
|
||||
#3 0xffffffff80edf832 at trap_fatal+0x322
|
||||
#4 0xffffffff80edf889 at trap_pfault+0x49
|
||||
#5 0xffffffff80edf0c6 at trap+0x286
|
||||
#6 0xffffffff80ec3641 at calltrap+0x8
|
||||
#7 0xffffffff80ae96e1 at m_copydata+0x61
|
||||
#8 0xffffffff80c05ba7 at sctp_sosend+0x157
|
||||
#9 0xffffffff80afa411 at kern_sendit+0x291
|
||||
#10 0xffffffff80afa773 at sendit+0x1a3
|
||||
#11 0xffffffff80afa831 at sys_sendmsg+0x61
|
||||
#12 0xffffffff80ee0394 at amd64_syscall+0x6c4
|
||||
#13 0xffffffff80ec392b at Xfast_syscall+0xfb
|
||||
`: `Fatal trap 12: page fault while in kernel mode in sctp_sosend`,
|
||||
|
||||
`
|
||||
Fatal trap 9: general protection fault while in kernel mode
|
||||
cpuid = 0; apic id = 00
|
||||
instruction pointer = 0x20:0xffffffff80ac2563
|
||||
stack pointer = 0x28:0xfffffe00003bd6e0
|
||||
frame pointer = 0x28:0xfffffe00003bd720
|
||||
code segment = base 0x0, limit 0xfffff, type 0x1b
|
||||
= DPL 0, pres 1, long 1, def32 0, gran 1
|
||||
processor eflags = resume, IOPL = 0
|
||||
current process = 51304 (syz-executor5)
|
||||
trap number = 9
|
||||
panic: general protection fault
|
||||
cpuid = 0
|
||||
KDB: stack backtrace:
|
||||
#0 0xffffffff80aada97 at kdb_backtrace+0x67
|
||||
#1 0xffffffff80a6bb76 at vpanic+0x186
|
||||
#2 0xffffffff80a6b9e3 at panic+0x43
|
||||
#3 0xffffffff80edf832 at trap_fatal+0x322
|
||||
#4 0xffffffff80edee9e at trap+0x5e
|
||||
#5 0xffffffff80ec3641 at calltrap+0x8
|
||||
#6 0xffffffff80a6780b at __rw_wlock_hard+0x32b
|
||||
#7 0xffffffff80c65e72 at udp_close+0x142
|
||||
#8 0xffffffff80af2b41 at soclose+0xe1
|
||||
#9 0xffffffff80a1ace9 at closef+0x269
|
||||
#10 0xffffffff80a1a7bd at fdescfree_fds+0x7d
|
||||
#11 0xffffffff80a1a397 at fdescfree+0x517
|
||||
#12 0xffffffff80a29348 at exit1+0x508
|
||||
#13 0xffffffff80a28e3d at sys_sys_exit+0xd
|
||||
#14 0xffffffff80ee0394 at amd64_syscall+0x6c4
|
||||
#15 0xffffffff80ec392b at Xfast_syscall+0xfb
|
||||
`: `Fatal trap 9: general protection fault while in kernel mode in udp_close`,
|
||||
|
||||
`
|
||||
panic: ffs_write: type 0xfffff80036275ce8 8 (0,230)
|
||||
cpuid = 0
|
||||
KDB: stack backtrace:
|
||||
#0 0xffffffff80aada97 at kdb_backtrace+0x67
|
||||
#1 0xffffffff80a6bb76 at vpanic+0x186
|
||||
#2 0xffffffff80a6b9e3 at panic+0x43
|
||||
#3 0xffffffff80d3611c at ffs_write+0x57c
|
||||
#4 0xffffffff8104c6b1 at VOP_WRITE_APV+0x111
|
||||
#5 0xffffffff80b3ade0 at vn_write+0x240
|
||||
#6 0xffffffff80b36902 at vn_io_fault+0x112
|
||||
#7 0xffffffff80ac8d08 at dofilewrite+0xc8
|
||||
#8 0xffffffff80ac87fb at sys_write+0xdb
|
||||
#9 0xffffffff80ee0394 at amd64_syscall+0x6c4
|
||||
#10 0xffffffff80ec392b at Xfast_syscall+0xfb
|
||||
`: `panic: ffs_write: type ADDR X (Y,Z)`,
|
||||
}
|
@ -150,9 +150,6 @@ func (ctx *linux) Parse(output []byte) (desc string, text []byte, start int, end
|
||||
return
|
||||
}
|
||||
desc = extractDescription(output[start:], oops)
|
||||
if len(desc) > 0 && desc[len(desc)-1] == '\r' {
|
||||
desc = desc[:len(desc)-1]
|
||||
}
|
||||
// Executor PIDs are not interesting.
|
||||
desc = executorRe.ReplaceAllLiteralString(desc, "syz-executor")
|
||||
// Replace that everything looks like an address with "ADDR",
|
||||
@ -167,48 +164,9 @@ func (ctx *linux) Parse(output []byte) (desc string, text []byte, start int, end
|
||||
desc = funcRe.ReplaceAllString(desc, "$1")
|
||||
// CPU numbers are not interesting.
|
||||
desc = cpuRe.ReplaceAllLiteralString(desc, "CPU")
|
||||
// Corrupted/intermixed lines can be very long.
|
||||
const maxDescLen = 180
|
||||
if len(desc) > maxDescLen {
|
||||
desc = desc[:maxDescLen]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func extractDescription(output []byte, oops *oops) string {
|
||||
result := ""
|
||||
startPos := -1
|
||||
for _, format := range oops.formats {
|
||||
match := format.re.FindSubmatchIndex(output)
|
||||
if match == nil {
|
||||
continue
|
||||
}
|
||||
if startPos != -1 && startPos <= match[0] {
|
||||
continue
|
||||
}
|
||||
startPos = match[0]
|
||||
var args []interface{}
|
||||
for i := 2; i < len(match); i += 2 {
|
||||
args = append(args, string(output[match[i]:match[i+1]]))
|
||||
}
|
||||
result = fmt.Sprintf(format.fmt, args...)
|
||||
}
|
||||
if result != "" {
|
||||
return result
|
||||
}
|
||||
pos := bytes.Index(output, oops.header)
|
||||
if pos == -1 {
|
||||
panic("non matching oops")
|
||||
}
|
||||
end := bytes.IndexByte(output[pos:], '\n')
|
||||
if end == -1 {
|
||||
end = len(output)
|
||||
} else {
|
||||
end += pos
|
||||
}
|
||||
return string(output[pos:end])
|
||||
}
|
||||
|
||||
func (ctx *linux) Symbolize(text []byte) ([]byte, error) {
|
||||
symb := symbolizer.NewSymbolizer()
|
||||
defer symb.Close()
|
||||
|
@ -6,7 +6,6 @@ package report
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/syzkaller/pkg/symbolizer"
|
||||
@ -705,7 +704,7 @@ WARNING: /etc/ssh/moduli does not exist, using fixed modulus
|
||||
|
||||
`
|
||||
[ 92.396607] general protection fault: 0000 [#1] [ 387.811073] audit: type=1326 audit(1486238739.637:135): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=10020 comm="syz-executor1" exe="/root/syz-executor1" sig=31 arch=c000003e syscall=202 compat=0 ip=0x44fad9 code=0x0
|
||||
`: `general protection fault: 0000 [#1] [ 387.NUM] audit: type=1326 audit(ADDR.637:LINE): auid=ADDR uid=0 gid=0 ses=ADDR pid=NUM comm="syz-executor" exe="/root/syz-executor" sig=31 arc`,
|
||||
`: `general protection fault: 0000 [#1] [ 387.NUM] audit: type=1326 audit(ADDR.637:LINE): auid=ADDR uid=0 gid=0 ses=ADDR pid=NUM comm="syz-executor" exe="/root/s`,
|
||||
|
||||
`
|
||||
[ 40.438790] BUG: Bad page map in process syz-executor6 pte:ffff8801a700ff00 pmd:1a700f067
|
||||
@ -778,36 +777,7 @@ other info that might help us debug this:
|
||||
[ 16.763144] [syscamera][msm_companion_pll_init::594][BIN_INFO::0x0008][WAFER_INFO::0xcf80][voltage 0.775]
|
||||
`: ``,
|
||||
}
|
||||
reporter, err := NewReporter("linux", "", "", nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for log, crash := range tests {
|
||||
if strings.Index(log, "\r\n") != -1 {
|
||||
continue
|
||||
}
|
||||
tests[strings.Replace(log, "\n", "\r\n", -1)] = crash
|
||||
}
|
||||
for log, crash := range tests {
|
||||
containsCrash := reporter.ContainsCrash([]byte(log))
|
||||
expectCrash := (crash != "")
|
||||
if expectCrash && !containsCrash {
|
||||
t.Fatalf("ContainsCrash did not find crash")
|
||||
}
|
||||
if !expectCrash && containsCrash {
|
||||
t.Fatalf("ContainsCrash found unexpected crash")
|
||||
}
|
||||
desc, _, _, _ := reporter.Parse([]byte(log))
|
||||
if desc == "" && crash != "" {
|
||||
t.Fatalf("did not find crash message '%v' in:\n%v", crash, log)
|
||||
}
|
||||
if desc != "" && crash == "" {
|
||||
t.Fatalf("found bogus crash message '%v' in:\n%v", desc, log)
|
||||
}
|
||||
if desc != crash {
|
||||
t.Fatalf("extracted bad crash message:\n%+q\nwant:\n%+q", desc, crash)
|
||||
}
|
||||
}
|
||||
testParse(t, "linux", tests)
|
||||
}
|
||||
|
||||
func TestLinuxIgnores(t *testing.T) {
|
||||
|
@ -113,6 +113,48 @@ func matchOops(line []byte, oops *oops, ignores []*regexp.Regexp) int {
|
||||
return match
|
||||
}
|
||||
|
||||
func extractDescription(output []byte, oops *oops) string {
|
||||
desc := ""
|
||||
startPos := -1
|
||||
for _, format := range oops.formats {
|
||||
match := format.re.FindSubmatchIndex(output)
|
||||
if match == nil {
|
||||
continue
|
||||
}
|
||||
if startPos != -1 && startPos <= match[0] {
|
||||
continue
|
||||
}
|
||||
startPos = match[0]
|
||||
var args []interface{}
|
||||
for i := 2; i < len(match); i += 2 {
|
||||
args = append(args, string(output[match[i]:match[i+1]]))
|
||||
}
|
||||
desc = fmt.Sprintf(format.fmt, args...)
|
||||
}
|
||||
if desc == "" {
|
||||
pos := bytes.Index(output, oops.header)
|
||||
if pos == -1 {
|
||||
panic("non matching oops")
|
||||
}
|
||||
end := bytes.IndexByte(output[pos:], '\n')
|
||||
if end == -1 {
|
||||
end = len(output)
|
||||
} else {
|
||||
end += pos
|
||||
}
|
||||
desc = string(output[pos:end])
|
||||
}
|
||||
if len(desc) > 0 && desc[len(desc)-1] == '\r' {
|
||||
desc = desc[:len(desc)-1]
|
||||
}
|
||||
// Corrupted/intermixed lines can be very long.
|
||||
const maxDescLen = 180
|
||||
if len(desc) > maxDescLen {
|
||||
desc = desc[:maxDescLen]
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
// replace replaces [start:end] in where with what, inplace.
|
||||
func replace(where []byte, start, end int, what []byte) []byte {
|
||||
if len(what) >= end-start {
|
||||
|
@ -5,6 +5,7 @@ package report
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -38,3 +39,36 @@ func TestReplace(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testParse(t *testing.T, os string, tests map[string]string) {
|
||||
reporter, err := NewReporter(os, "", "", nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for log, crash := range tests {
|
||||
if strings.Index(log, "\r\n") != -1 {
|
||||
continue
|
||||
}
|
||||
tests[strings.Replace(log, "\n", "\r\n", -1)] = crash
|
||||
}
|
||||
for log, crash := range tests {
|
||||
containsCrash := reporter.ContainsCrash([]byte(log))
|
||||
expectCrash := (crash != "")
|
||||
if expectCrash && !containsCrash {
|
||||
t.Fatalf("ContainsCrash did not find crash")
|
||||
}
|
||||
if !expectCrash && containsCrash {
|
||||
t.Fatalf("ContainsCrash found unexpected crash")
|
||||
}
|
||||
desc, _, _, _ := reporter.Parse([]byte(log))
|
||||
if desc == "" && crash != "" {
|
||||
t.Fatalf("did not find crash message '%v' in:\n%v", crash, log)
|
||||
}
|
||||
if desc != "" && crash == "" {
|
||||
t.Fatalf("found bogus crash message '%v' in:\n%v", desc, log)
|
||||
}
|
||||
if desc != crash {
|
||||
t.Fatalf("extracted bad crash message:\n%+q\nwant:\n%+q", desc, crash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user