• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 syzkaller project authors. All rights reserved.
2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3
4package report
5
6import (
7	"bytes"
8	"regexp"
9)
10
11type gvisor struct {
12	ignores []*regexp.Regexp
13}
14
15func ctorGvisor(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) {
16	ctx := &gvisor{
17		ignores: ignores,
18	}
19	suppressions := []string{
20		"fatal error: runtime: out of memory",
21		"fatal error: runtime: cannot allocate memory",
22		"panic: ptrace sysemu failed: no such process",     // OOM kill
23		"panic: ptrace set fpregs failed: no such process", // OOM kill
24		"panic: ptrace set regs failed: no such process",   // OOM kill
25		"panic: failed to start executor binary",
26		"panic: executor failed: pthread_create failed",
27		"ERROR: ThreadSanitizer", // Go race failing due to OOM.
28		"FATAL: ThreadSanitizer",
29	}
30	return ctx, suppressions, nil
31}
32
33func (ctx *gvisor) ContainsCrash(output []byte) bool {
34	return containsCrash(output, gvisorOopses, ctx.ignores)
35}
36
37func (ctx *gvisor) Parse(output []byte) *Report {
38	rep := simpleLineParser(output, gvisorOopses, nil, ctx.ignores)
39	if rep == nil {
40		return nil
41	}
42	rep.Title = replaceTable(gvisorTitleReplacement, rep.Title)
43	rep.Report = ctx.shortenReport(rep.Report)
44	return rep
45}
46
47func (ctx *gvisor) shortenReport(report []byte) []byte {
48	// gvisor panics include stacks of all goroutines.
49	// This output is too lengthy for report and not very useful.
50	// So we always take 5 lines from report and then cut it at the next empty line.
51	// The intention is to capture panic header and traceback of the first goroutine.
52	pos := 0
53	for i := 0; i < 5; i++ {
54		pos1 := bytes.IndexByte(report[pos:], '\n')
55		if pos1 == -1 {
56			return report
57		}
58		pos += pos1 + 1
59	}
60	end := bytes.Index(report[pos:], []byte{'\n', '\n'})
61	if end == -1 {
62		return report
63	}
64	if bytes.Contains(report, []byte("WARNING: DATA RACE")) {
65		// For data races extract both stacks.
66		end2 := bytes.Index(report[pos+end+2:], []byte{'\n', '\n'})
67		if end2 != -1 {
68			end += end2 + 2
69		}
70	}
71	return report[:pos+end+1]
72}
73
74func (ctx *gvisor) Symbolize(rep *Report) error {
75	return nil
76}
77
78var gvisorTitleReplacement = []replacement{
79	{
80		regexp.MustCompile(`container ".*"`),
81		"container NAME",
82	},
83}
84
85var gvisorOopses = []*oops{
86	{
87		[]byte("panic:"),
88		[]oopsFormat{
89			{
90				title:        compile("panic:(.*)"),
91				fmt:          "panic:%[1]v",
92				noStackTrace: true,
93			},
94		},
95		[]*regexp.Regexp{},
96	},
97	{
98		[]byte("Panic:"),
99		[]oopsFormat{
100			{
101				title:        compile("Panic:(.*)"),
102				fmt:          "Panic:%[1]v",
103				noStackTrace: true,
104			},
105		},
106		[]*regexp.Regexp{},
107	},
108	{
109		[]byte("fatal error:"),
110		[]oopsFormat{
111			{
112				title:        compile("fatal error:(.*)"),
113				fmt:          "fatal error:%[1]v",
114				noStackTrace: true,
115			},
116		},
117		[]*regexp.Regexp{},
118	},
119	{
120		[]byte("runtime error:"),
121		[]oopsFormat{
122			{
123				title:        compile("runtime error:(.*)"),
124				fmt:          "runtime error:%[1]v",
125				noStackTrace: true,
126			},
127		},
128		[]*regexp.Regexp{},
129	},
130	{
131		[]byte("SIGSEGV:"),
132		[]oopsFormat{
133			{
134				title:        compile("SIGSEGV:(.*)"),
135				fmt:          "SIGSEGV:%[1]v",
136				noStackTrace: true,
137			},
138		},
139		[]*regexp.Regexp{},
140	},
141	{
142		[]byte("SIGBUS:"),
143		[]oopsFormat{
144			{
145				title:        compile("SIGBUS:(.*)"),
146				fmt:          "SIGBUS:%[1]v",
147				noStackTrace: true,
148			},
149		},
150		[]*regexp.Regexp{},
151	},
152	{
153		[]byte("FATAL ERROR:"),
154		[]oopsFormat{
155			{
156				title:        compile("FATAL ERROR:(.*)"),
157				fmt:          "FATAL ERROR:%[1]v",
158				noStackTrace: true,
159			},
160		},
161		[]*regexp.Regexp{},
162	},
163	{
164		[]byte("WARNING: DATA RACE"),
165		[]oopsFormat{
166			{
167				title:        compile("WARNING: DATA RACE"),
168				report:       compile("WARNING: DATA RACE\n(?:.*\n)*?  (?:[a-zA-Z0-9./-_]+/)([a-zA-Z0-9.()*_]+)\\(\\)\n"),
169				fmt:          "DATA RACE in %[1]v",
170				noStackTrace: true,
171			},
172		},
173		[]*regexp.Regexp{},
174	},
175	{
176		[]byte("Invalid request partialResult"),
177		[]oopsFormat{
178			{
179				title:        compile("Invalid request partialResult"),
180				report:       compile("Invalid request partialResult .* for (.*) operation"),
181				fmt:          "Invalid request partialResult in %[1]v",
182				noStackTrace: true,
183			},
184		},
185		[]*regexp.Regexp{},
186	},
187}
188