aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-09-26 12:02:43 +0200
committerDmitry Vyukov <dvyukov@google.com>2018-09-26 12:02:43 +0200
commitdb716d6653d073b0abfb51186cd4ac2d5418c9c6 (patch)
tree3441a3d043c0ef52cbb5241ad283ffaeb6fb968a /pkg
parent455b6354e8fc3c74fbbc436cc611f113d884f7a3 (diff)
pkg/report: fix guilty file extraction
Account for the case that some file names can appear _before_ crash report starts. Start extracting guilty file starting from StartPos.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/report/linux.go47
-rw-r--r--pkg/report/report.go15
-rw-r--r--pkg/report/report_test.go22
-rw-r--r--pkg/report/testdata/linux/guilty/201
-rw-r--r--pkg/report/testdata/linux/guilty/3977
5 files changed, 124 insertions, 38 deletions
diff --git a/pkg/report/linux.go b/pkg/report/linux.go
index e23f7e32c..1880298b6 100644
--- a/pkg/report/linux.go
+++ b/pkg/report/linux.go
@@ -27,7 +27,7 @@ type linux struct {
consoleOutputRe *regexp.Regexp
questionableRe *regexp.Regexp
guiltyFileBlacklist []*regexp.Regexp
- reportStartIgnores [][]byte
+ reportStartIgnores []*regexp.Regexp
infoMessagesWithStack [][]byte
eoi []byte
}
@@ -82,10 +82,10 @@ func ctorLinux(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter,
regexp.MustCompile(`^fs/proc/generic.c`),
}
// These pattern do _not_ start a new report, i.e. can be in a middle of another report.
- ctx.reportStartIgnores = [][]byte{
- []byte("invalid opcode: 0000"),
- []byte("Kernel panic - not syncing: panic_on_warn set"),
- []byte("unregister_netdevice: waiting for"),
+ ctx.reportStartIgnores = []*regexp.Regexp{
+ compile(`invalid opcode: 0000`),
+ compile(`Kernel panic - not syncing: panic_on_warn set`),
+ compile(`unregister_netdevice: waiting for`),
}
// These pattern math kernel reports which are not bugs in itself but contain stack traces.
// If we see them in the middle of another report, we know that the report is potentially corrupted.
@@ -200,14 +200,7 @@ func (ctx *linux) parseOutput(output []byte) (
startPos = pos
break
} else if secondReportPos == 0 {
- ignored := false
- for _, ignore := range ctx.reportStartIgnores {
- if bytes.Contains(line, ignore) {
- ignored = true
- break
- }
- }
- if !ignored {
+ if !matchesAny(line, ctx.reportStartIgnores) {
secondReportPos = pos
}
}
@@ -274,20 +267,22 @@ func (ctx *linux) parseOutput(output []byte) (
}
func (ctx *linux) Symbolize(rep *Report) error {
- if ctx.vmlinux == "" {
- return nil
- }
- symbolized, err := ctx.symbolize(rep.Report)
- if err != nil {
- return err
+ if ctx.vmlinux != "" {
+ symbolized, err := ctx.symbolize(rep.Report)
+ if err != nil {
+ return err
+ }
+ rep.Report = symbolized
}
- rep.Report = symbolized
- guiltyFile := ctx.extractGuiltyFile(rep.Report)
- if guiltyFile != "" {
- rep.Maintainers, err = ctx.getMaintainers(guiltyFile)
+ // We still do this even if we did not symbolize,
+ // because tests pass in already symbolized input.
+ rep.guiltyFile = ctx.extractGuiltyFile(rep)
+ if rep.guiltyFile != "" {
+ maintainers, err := ctx.getMaintainers(rep.guiltyFile)
if err != nil {
return err
}
+ rep.Maintainers = maintainers
}
return nil
}
@@ -381,7 +376,8 @@ func symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, err
return symbolized
}
-func (ctx *linux) extractGuiltyFile(report []byte) string {
+func (ctx *linux) extractGuiltyFile(rep *Report) string {
+ report := rep.Report[rep.StartPos:]
if linuxRcuStall.Match(report) {
// Special case for rcu stalls.
// There are too many frames that we want to skip before actual guilty frames,
@@ -412,6 +408,9 @@ nextFile:
}
func (ctx *linux) getMaintainers(file string) ([]string, error) {
+ if ctx.kernelSrc == "" {
+ return nil, nil
+ }
mtrs, err := ctx.getMaintainersImpl(file, false)
if err != nil {
return nil, err
diff --git a/pkg/report/report.go b/pkg/report/report.go
index 27a71e937..e97930fe0 100644
--- a/pkg/report/report.go
+++ b/pkg/report/report.go
@@ -43,8 +43,10 @@ type Report struct {
Corrupted bool
// CorruptedReason contains reason why the report is marked as corrupted.
CorruptedReason string
- // Maintainers is list of maintainer emails.
+ // Maintainers is list of maintainer emails (filled in by Symbolize).
Maintainers []string
+ // guiltyFile is the source file that we think is to blame for the crash (filled in by Symbolize).
+ guiltyFile string
}
// NewReporter creates reporter for the specified OS/Type.
@@ -189,17 +191,6 @@ func sanitizeTitle(title string) string {
return strings.TrimSpace(string(res))
}
-type guilter interface {
- extractGuiltyFile([]byte) string
-}
-
-func (wrap reporterWrapper) extractGuiltyFile(report []byte) string {
- if g, ok := wrap.Reporter.(guilter); ok {
- return g.extractGuiltyFile(report)
- }
- panic("not implemented")
-}
-
type oops struct {
header []byte
formats []oopsFormat
diff --git a/pkg/report/report_test.go b/pkg/report/report_test.go
index 7012b54f2..2eaf54fa6 100644
--- a/pkg/report/report_test.go
+++ b/pkg/report/report_test.go
@@ -220,8 +220,26 @@ func testGuiltyFile(t *testing.T, reporter Reporter, fn string) {
}
file := string(data[len(prefix) : len(prefix)+nlnl])
report := data[len(prefix)+nlnl:]
- if guilty := reporter.(guilter).extractGuiltyFile(report); guilty != file {
- t.Fatalf("got guilty %q, want %q", guilty, file)
+ rep := reporter.Parse(report)
+ if rep == nil {
+ t.Fatalf("did not find crash in the input")
+ }
+ // Parse doesn't generally run on already symbolized output,
+ // but here we run it on symbolized output because we can't symbolize in tests.
+ // The problem is with duplicated lines due to inlined frames,
+ // Parse can strip such report after first title line because it thinks
+ // that the duplicated title line is beginning on another report.
+ // In such case we restore whole report, but still keep StartPos that
+ // Parse produces at least in some cases.
+ if !bytes.HasSuffix(report, rep.Report) {
+ rep.Report = report
+ rep.StartPos = 0
+ }
+ if err := reporter.Symbolize(rep); err != nil {
+ t.Fatalf("failed to symbolize report: %v", err)
+ }
+ if rep.guiltyFile != file {
+ t.Fatalf("got guilty %q, want %q", rep.guiltyFile, file)
}
}
diff --git a/pkg/report/testdata/linux/guilty/20 b/pkg/report/testdata/linux/guilty/20
index 0fc073699..b95a5b74d 100644
--- a/pkg/report/testdata/linux/guilty/20
+++ b/pkg/report/testdata/linux/guilty/20
@@ -1,3 +1,4 @@
FILE: driver/foo/lib/foo.c
+WARNING: CPU: 2 PID: 24023 at kernel/locking/lockdep.c:3344 __lock_acquire+0x10e5/0x3690 kernel/locking/lockdep.c:3344
driver/foo/lib/foo.c:10
diff --git a/pkg/report/testdata/linux/guilty/39 b/pkg/report/testdata/linux/guilty/39
new file mode 100644
index 000000000..79bbf1223
--- /dev/null
+++ b/pkg/report/testdata/linux/guilty/39
@@ -0,0 +1,77 @@
+FILE: security/apparmor/policy_ns.c
+
+ sock_common_setsockopt+0x9a/0xe0 net/core/sock.c:3038
+ __sys_setsockopt+0x1ba/0x3c0 net/socket.c:1902
+ __do_sys_setsockopt net/socket.c:1913 [inline]
+ __se_sys_setsockopt net/socket.c:1910 [inline]
+ __x64_sys_setsockopt+0xbe/0x150 net/socket.c:1910
+ do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
+==================================================================
+BUG: KASAN: global-out-of-bounds in memcmp+0xe3/0x160 lib/string.c:861
+Read of size 1 at addr ffffffff88000008 by task syz-executor0/10914
+
+ entry_SYSCALL_64_after_hwframe+0x49/0xbe
+RIP: 0033:0x457579
+Code: 1d b4 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 eb b3 fb ff c3 66 2e 0f 1f 84 00 00 00 00
+RSP: 002b:00007f4c14533c78 EFLAGS: 00000246 ORIG_RAX: 0000000000000036
+RAX: ffffffffffffffda RBX: 00007f4c14533c90 RCX: 0000000000457579
+RDX: 0000000000000040 RSI: 0000000000000000 RDI: 0000000000000003
+RBP: 000000000072bf00 R08: 0000000000000004 R09: 0000000000000000
+R10: 0000000020000080 R11: 0000000000000246 R12: 00007f4c145346d4
+R13: 00000000004c3ed9 R14: 00000000004d6260 R15: 0000000000000004
+CPU: 0 PID: 10914 Comm: syz-executor0 Not tainted 4.19.0-rc5+ #252
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+Call Trace:
+ __dump_stack lib/dump_stack.c:77 [inline]
+ dump_stack+0x1c4/0x2b4 lib/dump_stack.c:113
+ print_address_description.cold.8+0x58/0x1ff mm/kasan/report.c:256
+ kasan_report_error mm/kasan/report.c:354 [inline]
+ kasan_report.cold.9+0x242/0x309 mm/kasan/report.c:412
+ __asan_report_load1_noabort+0x14/0x20 mm/kasan/report.c:430
+ memcmp+0xe3/0x160 lib/string.c:861
+ strnstr+0x4b/0x70 lib/string.c:934
+ __aa_lookupn_ns+0xc1/0x570 security/apparmor/policy_ns.c:209
+ aa_lookupn_ns+0x88/0x1e0 security/apparmor/policy_ns.c:240
+ aa_fqlookupn_profile+0x1b9/0x1010 security/apparmor/policy.c:468
+ fqlookupn_profile+0x80/0xc0 security/apparmor/label.c:1844
+ aa_label_strn_parse+0xa3a/0x1230 security/apparmor/label.c:1908
+ aa_label_parse+0x42/0x50 security/apparmor/label.c:1943
+ aa_change_profile+0x513/0x3510 security/apparmor/domain.c:1362
+ apparmor_setprocattr+0xa8b/0x1150 security/apparmor/lsm.c:656
+ security_setprocattr+0x66/0xc0 security/security.c:1298
+ proc_pid_attr_write+0x301/0x540 fs/proc/base.c:2555
+ __vfs_write+0x119/0x9f0 fs/read_write.c:485
+ vfs_write+0x1fc/0x560 fs/read_write.c:549
+ ksys_write+0x101/0x260 fs/read_write.c:598
+ __do_sys_write fs/read_write.c:610 [inline]
+ __se_sys_write fs/read_write.c:607 [inline]
+ __x64_sys_write+0x73/0xb0 fs/read_write.c:607
+ do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
+ entry_SYSCALL_64_after_hwframe+0x49/0xbe
+RIP: 0033:0x457579
+Code: 1d b4 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 eb b3 fb ff c3 66 2e 0f 1f 84 00 00 00 00
+RSP: 002b:00007f5a92ec2c78 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
+RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000457579
+RDX: 000000000000002c RSI: 00000000200000c0 RDI: 0000000000000004
+RBP: 000000000072bf00 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 00007f5a92ec36d4
+R13: 00000000004c5454 R14: 00000000004d8c78 R15: 00000000ffffffff
+
+CPU: 1 PID: 10921 Comm: syz-executor3 Not tainted 4.19.0-rc5+ #252
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+The buggy address belongs to the variable:
+ __start_rodata+0x8/0x1000
+Call Trace:
+ __dump_stack lib/dump_stack.c:77 [inline]
+ dump_stack+0x1c4/0x2b4 lib/dump_stack.c:113
+
+Memory state around the buggy address:
+ ffffffff87ffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffffffff87ffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ fail_dump lib/fault-inject.c:51 [inline]
+ should_fail.cold.4+0xa/0x17 lib/fault-inject.c:149
+ffffffff88000000: 00 fa fa fa fa fa fa fa 00 01 fa fa fa fa fa fa
+ ^
+ ffffffff88000080: 00 00 00 07 fa fa fa fa 00 04 fa fa fa fa fa fa
+ ffffffff88000100: 05 fa fa fa fa fa fa fa 00 00 00 00 05 fa fa fa
+==================================================================