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