github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/report/gvisor.go (about) 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 4 package report 5 6 import ( 7 "bytes" 8 "regexp" 9 ) 10 11 type gvisor struct { 12 *config 13 } 14 15 func ctorGvisor(cfg *config) (reporterImpl, []string, error) { 16 ctx := &gvisor{ 17 config: cfg, 18 } 19 suppressions := []string{ 20 "panic: ptrace sysemu failed: no such process", // OOM kill 21 `panic: ptrace (s|g)et fpregs.* failed: no such process`, // OOM kill 22 `panic: ptrace (s|g)et regs.* failed: no such process`, // OOM kill 23 "panic: error initializing first thread: resource temporarily unavailable", // PID exhaustion 24 "panic: unable to activate mm: creating stub process: resource temporarily unavailable", // PID exhaustion 25 "panic: executor failed: pthread_create failed", // PID exhaustion 26 "panic: failed to start executor binary", 27 "panic: error mapping run data: error mapping runData: cannot allocate memory", 28 "race: limit on 8128 simultaneously alive goroutines is exceeded, dying", 29 "ERROR: ThreadSanitizer", // Go race failing due to OOM. 30 "FATAL: ThreadSanitizer", 31 "ThreadSanitizer: clock allocator overflow \\(65536\\*1024\\). Dying.", 32 } 33 return ctx, suppressions, nil 34 } 35 36 func (ctx *gvisor) ContainsCrash(output []byte) bool { 37 return containsCrash(output, gvisorOopses, ctx.ignores) 38 } 39 40 func (ctx *gvisor) Parse(output []byte) *Report { 41 rep := simpleLineParser(output, gvisorOopses, nil, ctx.ignores) 42 if rep == nil { 43 return nil 44 } 45 rep.Title = replaceTable(gvisorTitleReplacement, rep.Title) 46 rep.Report = ctx.shortenReport(rep.Report) 47 return rep 48 } 49 50 func (ctx *gvisor) shortenReport(report []byte) []byte { 51 // gvisor panics include stacks of all goroutines. 52 // This output is too lengthy for report and not very useful. 53 // So we always take 5 lines from report and then cut it at the next empty line. 54 // The intention is to capture panic header and traceback of the first goroutine. 55 pos := 0 56 for i := 0; i < 5; i++ { 57 pos1 := bytes.IndexByte(report[pos:], '\n') 58 if pos1 == -1 { 59 return report 60 } 61 pos += pos1 + 1 62 } 63 end := bytes.Index(report[pos:], []byte{'\n', '\n'}) 64 if end == -1 { 65 return report 66 } 67 if bytes.Contains(report, []byte("WARNING: DATA RACE")) { 68 // For data races extract both stacks. 69 end2 := bytes.Index(report[pos+end+2:], []byte{'\n', '\n'}) 70 if end2 != -1 { 71 end += end2 + 2 72 } 73 } 74 return report[:pos+end+1] 75 } 76 77 func (ctx *gvisor) Symbolize(rep *Report) error { 78 return nil 79 } 80 81 var gvisorTitleReplacement = []replacement{ 82 { 83 regexp.MustCompile(`container ".*"`), 84 "container NAME", 85 }, 86 { 87 regexp.MustCompile(`sandbox ".*"`), 88 "sandbox NAME", 89 }, 90 { 91 regexp.MustCompile(`(pid|PID) [0-9]+`), 92 "pid X", 93 }, 94 } 95 96 var gvisorOopses = append([]*oops{ 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("SIGSEGV:"), 110 []oopsFormat{ 111 { 112 title: compile("SIGSEGV:(.*)"), 113 fmt: "SIGSEGV:%[1]v", 114 noStackTrace: true, 115 }, 116 }, 117 []*regexp.Regexp{}, 118 }, 119 { 120 []byte("SIGBUS:"), 121 []oopsFormat{ 122 { 123 title: compile("SIGBUS:(.*)"), 124 fmt: "SIGBUS:%[1]v", 125 noStackTrace: true, 126 }, 127 }, 128 []*regexp.Regexp{}, 129 }, 130 { 131 []byte("FATAL ERROR:"), 132 []oopsFormat{ 133 { 134 title: compile("FATAL ERROR:(.*)"), 135 fmt: "FATAL ERROR:%[1]v", 136 noStackTrace: true, 137 }, 138 }, 139 []*regexp.Regexp{}, 140 }, 141 { 142 []byte("WARNING: DATA RACE"), 143 []oopsFormat{ 144 { 145 title: compile("WARNING: DATA RACE"), 146 report: compile("WARNING: DATA RACE\n(?:.*\n)*? (?:[a-zA-Z0-9./_-]+/)([a-zA-Z0-9.()*_]+)\\(\\)\n"), 147 fmt: "DATA RACE in %[1]v", 148 noStackTrace: true, 149 }, 150 }, 151 []*regexp.Regexp{}, 152 }, 153 { 154 []byte("Invalid request partialResult"), 155 []oopsFormat{ 156 { 157 title: compile("Invalid request partialResult"), 158 report: compile("Invalid request partialResult .* for (.*) operation"), 159 fmt: "Invalid request partialResult in %[1]v", 160 noStackTrace: true, 161 }, 162 }, 163 []*regexp.Regexp{}, 164 }, 165 { 166 []byte("fatal error:"), 167 []oopsFormat{ 168 { 169 title: compile("fatal error:(.*)"), 170 fmt: "fatal error:%[1]v", 171 noStackTrace: true, 172 }, 173 }, 174 []*regexp.Regexp{}, 175 }, 176 { 177 []byte("WARNING: BUG on"), 178 []oopsFormat{ 179 { 180 title: compile("WARNING: BUG on (.*)"), 181 fmt: "WARNING: BUG on %[1]v", 182 noStackTrace: true, 183 }, 184 }, 185 []*regexp.Regexp{}, 186 }, 187 }, commonOopses...)