github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/report/linux.go (about) 1 // Copyright 2017 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 "encoding/binary" 9 "fmt" 10 "path/filepath" 11 "regexp" 12 "strconv" 13 "strings" 14 "time" 15 16 "github.com/google/syzkaller/pkg/osutil" 17 "github.com/google/syzkaller/pkg/report/crash" 18 "github.com/google/syzkaller/pkg/symbolizer" 19 "github.com/google/syzkaller/pkg/vcs" 20 "github.com/google/syzkaller/sys/targets" 21 ) 22 23 type linux struct { 24 *config 25 vmlinux string 26 symbols map[string][]symbolizer.Symbol 27 consoleOutputRe *regexp.Regexp 28 taskContext *regexp.Regexp 29 cpuContext *regexp.Regexp 30 questionableFrame *regexp.Regexp 31 guiltyFileIgnores []*regexp.Regexp 32 guiltyLineIgnore *regexp.Regexp 33 reportStartIgnores []*regexp.Regexp 34 infoMessagesWithStack [][]byte 35 eoi []byte 36 symbolizerCache symbolizer.Cache 37 } 38 39 func ctorLinux(cfg *config) (reporterImpl, []string, error) { 40 var symbols map[string][]symbolizer.Symbol 41 vmlinux := "" 42 if cfg.kernelObj != "" { 43 vmlinux = filepath.Join(cfg.kernelObj, cfg.target.KernelObject) 44 var err error 45 symb := symbolizer.NewSymbolizer(cfg.target) 46 symbols, err = symb.ReadTextSymbols(vmlinux) 47 if err != nil { 48 return nil, nil, err 49 } 50 } 51 ctx := &linux{ 52 config: cfg, 53 vmlinux: vmlinux, 54 symbols: symbols, 55 } 56 // nolint: lll 57 ctx.consoleOutputRe = regexp.MustCompile(`^(?:\*\* [0-9]+ printk messages dropped \*\* )?(?:.* login: )?(?:\<[0-9]+\>)?\[ *[0-9]+\.[0-9]+\](\[ *(?:C|T)[0-9]+\])? `) 58 ctx.taskContext = regexp.MustCompile(`\[ *T[0-9]+\]`) 59 ctx.cpuContext = regexp.MustCompile(`\[ *C[0-9]+\]`) 60 ctx.questionableFrame = regexp.MustCompile(`(\[\<[0-9a-f]+\>\])? \? `) 61 ctx.eoi = []byte("<EOI>") 62 ctx.guiltyFileIgnores = []*regexp.Regexp{ 63 regexp.MustCompile(`.*\.h`), 64 regexp.MustCompile(`^lib/.*`), 65 regexp.MustCompile(`^virt/lib/.*`), 66 regexp.MustCompile(`^mm/kasan/.*`), 67 regexp.MustCompile(`^mm/kmsan/.*`), 68 regexp.MustCompile(`^kernel/kcov.c`), 69 regexp.MustCompile(`^mm/sl.b.c`), 70 regexp.MustCompile(`^mm/filemap.c`), 71 regexp.MustCompile(`^mm/folio-compat.c`), 72 regexp.MustCompile(`^mm/truncate.c`), 73 regexp.MustCompile(`^mm/memory.c`), 74 regexp.MustCompile(`^mm/percpu.*`), 75 regexp.MustCompile(`^mm/vmalloc.c`), 76 regexp.MustCompile(`^mm/page_alloc.c`), 77 regexp.MustCompile(`^mm/mempool.c`), 78 regexp.MustCompile(`^mm/util.c`), 79 regexp.MustCompile(`^kernel/rcu/.*`), 80 regexp.MustCompile(`^arch/.*/kernel/traps.c`), 81 regexp.MustCompile(`^arch/.*/kernel/unwind.*.c`), 82 regexp.MustCompile(`^arch/.*/mm/fault.c`), 83 regexp.MustCompile(`^arch/.*/mm/physaddr.c`), 84 regexp.MustCompile(`^arch/.*/kernel/stacktrace.c`), 85 regexp.MustCompile(`^arch/.*/kernel/apic/apic.c`), 86 regexp.MustCompile(`^arch/arm64/kernel/entry.*.c`), 87 regexp.MustCompile(`^arch/arm64/kernel/process\.c`), 88 regexp.MustCompile(`^kernel/locking/.*`), 89 regexp.MustCompile(`^kernel/panic.c`), 90 regexp.MustCompile(`^kernel/printk/printk.*.c`), 91 regexp.MustCompile(`^kernel/softirq.c`), 92 regexp.MustCompile(`^kernel/kthread.c`), 93 regexp.MustCompile(`^kernel/sched/.*.c`), 94 regexp.MustCompile(`^kernel/stacktrace.c`), 95 regexp.MustCompile(`^kernel/time/timer.c`), 96 regexp.MustCompile(`^kernel/workqueue.c`), 97 regexp.MustCompile(`^net/core/dev.c`), 98 regexp.MustCompile(`^net/core/sock.c`), 99 regexp.MustCompile(`^net/core/skbuff.c`), 100 regexp.MustCompile(`^fs/proc/generic.c`), 101 regexp.MustCompile(`^trusty/`), // Trusty sources are not in linux kernel tree. 102 regexp.MustCompile(`^drivers/usb/core/urb.c`), // WARNING in urb.c usually means a bug in a driver 103 } 104 ctx.guiltyLineIgnore = regexp.MustCompile(`(hardirqs|softirqs)\s+last\s+(enabled|disabled)|^Register r\d+ information`) 105 // These pattern do _not_ start a new report, i.e. can be in a middle of another report. 106 ctx.reportStartIgnores = []*regexp.Regexp{ 107 compile(`invalid opcode: 0000`), 108 compile(`Kernel panic - not syncing`), 109 compile(`unregister_netdevice: waiting for`), 110 // Double fault can happen during handling of paging faults 111 // if memory is badly corrupted. Also it usually happens 112 // synchronously, which means that maybe the report is not corrupted. 113 // But of course it can come from another CPU as well. 114 compile(`PANIC: double fault`), 115 compile(`Internal error:`), 116 } 117 // These pattern math kernel reports which are not bugs in itself but contain stack traces. 118 // If we see them in the middle of another report, we know that the report is potentially corrupted. 119 ctx.infoMessagesWithStack = [][]byte{ 120 []byte("vmalloc: allocation failure:"), 121 []byte("FAULT_INJECTION: forcing a failure"), 122 []byte("FAULT_FLAG_ALLOW_RETRY missing"), 123 } 124 suppressions := []string{ 125 "panic: failed to start executor binary", 126 "panic: executor failed: pthread_create failed", 127 "panic: failed to create temp dir", 128 "fatal error: unexpected signal during runtime execution", // presubmably OOM turned into SIGBUS 129 "signal SIGBUS: bus error", // presubmably OOM turned into SIGBUS 130 "Out of memory: Kill process .* \\(syz-fuzzer\\)", 131 "Out of memory: Kill process .* \\(sshd\\)", 132 "Killed process .* \\(syz-fuzzer\\)", 133 "Killed process .* \\(sshd\\)", 134 "lowmemorykiller: Killing 'syz-fuzzer'", 135 "lowmemorykiller: Killing 'sshd'", 136 "INIT: PANIC: segmentation violation!", 137 "\\*\\*\\* stack smashing detected \\*\\*\\*: terminated", 138 } 139 return ctx, suppressions, nil 140 } 141 142 const contextConsole = "console" 143 144 func (ctx *linux) ContainsCrash(output []byte) bool { 145 return containsCrash(output, linuxOopses, ctx.ignores) 146 } 147 148 func (ctx *linux) Parse(output []byte) *Report { 149 oops, startPos, context := ctx.findFirstOops(output) 150 if oops == nil { 151 return nil 152 } 153 for questionable := false; ; questionable = true { 154 rep := &Report{ 155 Output: output, 156 StartPos: startPos, 157 } 158 endPos, reportEnd, report, prefix := ctx.findReport(output, oops, startPos, context, questionable) 159 rep.EndPos = endPos 160 title, corrupted, altTitles, format := extractDescription(report[:reportEnd], oops, linuxStackParams) 161 if title == "" { 162 prefix = nil 163 report = output[rep.StartPos:rep.EndPos] 164 title, corrupted, altTitles, format = extractDescription(report, oops, linuxStackParams) 165 if title == "" { 166 panic(fmt.Sprintf("non matching oops for %q context=%q in:\n%s\n", 167 oops.header, context, report)) 168 } 169 } 170 rep.Title = title 171 rep.AltTitles = altTitles 172 rep.Corrupted = corrupted != "" 173 rep.CorruptedReason = corrupted 174 for _, line := range prefix { 175 rep.Report = append(rep.Report, line...) 176 rep.Report = append(rep.Report, '\n') 177 } 178 rep.reportPrefixLen = len(rep.Report) 179 rep.Report = append(rep.Report, report...) 180 setReportType(rep, oops, format) 181 if !rep.Corrupted { 182 rep.Corrupted, rep.CorruptedReason = ctx.isCorrupted(title, report, format) 183 } 184 if rep.CorruptedReason == corruptedNoFrames && context != contextConsole && !questionable { 185 // We used to look at questionable frame with the following incentive: 186 // """ 187 // Some crash reports have all frames questionable. 188 // So if we get a corrupted report because there are no frames, 189 // try again now looking at questionable frames. 190 // Only do this if we have a real context (CONFIG_PRINTK_CALLER=y), 191 // to be on the safer side. Without context it's too easy to use 192 // a stray frame from a wrong context. 193 // """ 194 // Most likely reports without proper stack traces were caused by a bug 195 // in the unwinder and are now fixed in 187b96db5ca7 "x86/unwind/orc: 196 // Fix unwind_get_return_address_ptr() for inactive tasks". 197 // Disable trying to use questionable frames for now. 198 useQuestionableFrames := false 199 if useQuestionableFrames { 200 continue 201 } 202 } 203 return rep 204 } 205 } 206 207 func (ctx *linux) findFirstOops(output []byte) (oops *oops, startPos int, context string) { 208 for pos, next := 0, 0; pos < len(output); pos = next + 1 { 209 next = bytes.IndexByte(output[pos:], '\n') 210 if next != -1 { 211 next += pos 212 } else { 213 next = len(output) 214 } 215 line := output[pos:next] 216 for _, oops1 := range linuxOopses { 217 if matchOops(line, oops1, ctx.ignores) { 218 oops = oops1 219 startPos = pos 220 context = ctx.extractContext(line) 221 return 222 } 223 } 224 } 225 return 226 } 227 228 // This method decides if the report prefix is already long enough to be cut on "Kernel panic - not 229 // syncing: panic_on_kmsan set ...". 230 func (ctx *linux) reportMinLines(oopsLine []byte) int { 231 if bytes.Contains(oopsLine, []byte("BUG: KMSAN:")) { 232 // KMSAN reports do not have the "Call trace" and some of the other lines which are 233 // present e.g. in KASAN reports. So we use a lower threshold for them. 234 return 16 235 } 236 return 22 237 } 238 239 // Yes, it is complex, but all state and logic are tightly coupled. It's unclear how to simplify it. 240 // nolint: gocyclo, gocognit 241 func (ctx *linux) findReport(output []byte, oops *oops, startPos int, context string, useQuestionable bool) ( 242 endPos, reportEnd int, report []byte, prefix [][]byte) { 243 // Prepend 5 lines preceding start of the report, 244 // they can contain additional info related to the report. 245 maxPrefix := 5 246 if ctx.taskContext.MatchString(context) { 247 // If we have CONFIG_PRINTK_CALLER, we collect more b/c it comes from the same task. 248 maxPrefix = 50 249 } 250 secondReportPos := 0 251 textLines := 0 252 skipText, cpuTraceback := false, false 253 oopsLine := []byte{} 254 for pos, next := 0, 0; pos < len(output); pos = next + 1 { 255 next = bytes.IndexByte(output[pos:], '\n') 256 if next != -1 { 257 next += pos 258 } else { 259 next = len(output) 260 } 261 line := output[pos:next] 262 context1 := ctx.extractContext(line) 263 stripped, questionable := ctx.stripLinePrefix(line, context1, useQuestionable) 264 if pos < startPos { 265 if context1 == context && len(stripped) != 0 && !questionable { 266 prefix = append(prefix, append([]byte{}, stripped...)) 267 if len(prefix) > maxPrefix { 268 prefix = prefix[1:] 269 } 270 } 271 continue 272 } 273 isOopsLine := pos == startPos 274 if isOopsLine { 275 oopsLine = line 276 } 277 278 for _, oops1 := range linuxOopses { 279 if !matchOops(line, oops1, ctx.ignores) { 280 if !isOopsLine && secondReportPos == 0 { 281 for _, pattern := range ctx.infoMessagesWithStack { 282 if bytes.Contains(line, pattern) { 283 secondReportPos = pos 284 break 285 } 286 } 287 } 288 continue 289 } 290 endPos = next 291 if !isOopsLine && secondReportPos == 0 { 292 if !matchesAny(line, ctx.reportStartIgnores) { 293 secondReportPos = pos 294 } 295 } 296 } 297 if !isOopsLine && (questionable || 298 context1 != context && (!cpuTraceback || !ctx.cpuContext.MatchString(context1))) { 299 continue 300 } 301 textLines++ 302 skipLine := skipText 303 if bytes.Contains(line, []byte("Disabling lock debugging due to kernel taint")) { 304 skipLine = true 305 } else if bytes.Contains(line, []byte("Sending NMI from CPU")) { 306 // If we are doing traceback of all CPUs, then we also need to preserve output 307 // from other CPUs regardless of what is the current context. 308 // Otherwise we will throw traceback away because it does not match the oops context. 309 cpuTraceback = true 310 } else if (bytes.Contains(line, []byte("Kernel panic - not syncing")) || 311 bytes.Contains(line, []byte("WARNING: possible circular locking dependency detected"))) && 312 textLines > ctx.reportMinLines(oopsLine) { 313 // If panic_on_warn set, then we frequently have 2 stacks: 314 // one for the actual report (or maybe even more than one), 315 // and then one for panic caused by panic_on_warn. This makes 316 // reports unnecessary long and the panic (current) stack 317 // is always present in the actual report. So we strip the 318 // panic message. However, we check that we have enough lines 319 // before the panic, because sometimes we have, for example, 320 // a single WARNING line without a stack and then the panic 321 // with the stack. 322 // Oops messages frequently induce possible deadlock reports 323 // because oops reporting introduces unexpected locking chains. 324 // So if we have enough of the actual oops, strip the deadlock message. 325 skipText = true 326 skipLine = true 327 } 328 if !isOopsLine && skipLine { 329 continue 330 } 331 report = append(report, stripped...) 332 report = append(report, '\n') 333 if secondReportPos == 0 || context != "" && context != contextConsole { 334 reportEnd = len(report) 335 } 336 } 337 return 338 } 339 340 func (ctx *linux) stripLinePrefix(line []byte, context string, useQuestionable bool) ([]byte, bool) { 341 if context == "" { 342 return line, false 343 } 344 start := bytes.Index(line, []byte("] ")) 345 line = line[start+2:] 346 if !bytes.Contains(line, ctx.eoi) { 347 // x86_64 prefix. 348 if ctx.questionableFrame.Match(line) { 349 pos := bytes.Index(line, []byte(" ? ")) 350 return line[pos+2:], !useQuestionable 351 } 352 // PowerPC suffix. 353 if bytes.HasSuffix(line, []byte(" (unreliable)")) { 354 return line[:len(line)-13], !useQuestionable 355 } 356 } 357 return line, false 358 } 359 360 func (ctx *linux) extractContext(line []byte) string { 361 match := ctx.consoleOutputRe.FindSubmatchIndex(line) 362 if match == nil { 363 return "" 364 } 365 if match[2] == -1 { 366 return contextConsole 367 } 368 return string(line[match[2]:match[3]]) 369 } 370 371 func (ctx *linux) Symbolize(rep *Report) error { 372 if ctx.vmlinux != "" { 373 if err := ctx.symbolize(rep); err != nil { 374 return err 375 } 376 } 377 rep.Report = ctx.decompileOpcodes(rep.Report, rep) 378 379 // Skip getting maintainers for Android fuzzing since the kernel source 380 // directory structure is different. 381 if ctx.config.vmType == "cuttlefish" || ctx.config.vmType == "proxyapp" { 382 return nil 383 } 384 385 // We still do this even if we did not symbolize, 386 // because tests pass in already symbolized input. 387 rep.GuiltyFile = ctx.extractGuiltyFile(rep) 388 if rep.GuiltyFile != "" { 389 maintainers, err := ctx.getMaintainers(rep.GuiltyFile) 390 if err != nil { 391 return err 392 } 393 rep.Recipients = maintainers 394 } 395 return nil 396 } 397 398 func (ctx *linux) symbolize(rep *Report) error { 399 symb := symbolizer.NewSymbolizer(ctx.config.target) 400 defer symb.Close() 401 symbFunc := func(bin string, pc uint64) ([]symbolizer.Frame, error) { 402 return ctx.symbolizerCache.Symbolize(symb.Symbolize, bin, pc) 403 } 404 var symbolized []byte 405 prefix := rep.reportPrefixLen 406 for _, line := range bytes.SplitAfter(rep.Report, []byte("\n")) { 407 line := bytes.Clone(line) 408 newLine := symbolizeLine(symbFunc, ctx.symbols, ctx.vmlinux, ctx.kernelBuildSrc, line) 409 if prefix > len(symbolized) { 410 prefix += len(newLine) - len(line) 411 } 412 symbolized = append(symbolized, newLine...) 413 } 414 oldReport := rep.Report 415 rep.Report = symbolized 416 oldPrefixLen := rep.reportPrefixLen 417 rep.reportPrefixLen = prefix 418 419 if len(rep.Report) > 0 && rep.reportPrefixLen > len(rep.Report) { 420 panic(fmt.Sprintf("invalid reportPrefixLen after symbolize: prefix %d -> %d,"+ 421 "report len: %d -> %d, old report: %q", 422 oldPrefixLen, rep.reportPrefixLen, len(oldReport), len(rep.Report), oldReport, 423 )) 424 } 425 return nil 426 } 427 428 func symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error), 429 symbols map[string][]symbolizer.Symbol, vmlinux, strip string, line []byte) []byte { 430 match := linuxSymbolizeRe.FindSubmatchIndex(line) 431 if match == nil { 432 return line 433 } 434 fn := line[match[2]:match[3]] 435 off, err := strconv.ParseUint(string(line[match[4]:match[5]]), 16, 64) 436 if err != nil { 437 return line 438 } 439 size, err := strconv.ParseUint(string(line[match[6]:match[7]]), 16, 64) 440 if err != nil { 441 return line 442 } 443 symb := symbols[string(fn)] 444 if len(symb) == 0 { 445 return line 446 } 447 var funcStart uint64 448 for _, s := range symb { 449 if funcStart == 0 || int(size) == s.Size { 450 funcStart = s.Addr 451 } 452 } 453 pc := funcStart + off 454 if !linuxRipFrame.Match(line) { 455 // Usually we have return PCs, so we need to look at the previous instruction. 456 // But RIP lines contain the exact faulting PC. 457 pc-- 458 } 459 frames, err := symbFunc(vmlinux, pc) 460 if err != nil || len(frames) == 0 { 461 return line 462 } 463 var symbolized []byte 464 for _, frame := range frames { 465 file := frame.File 466 file = strings.TrimPrefix(file, strip) 467 file = strings.TrimLeft(file, "./") 468 info := fmt.Sprintf(" %v:%v", file, frame.Line) 469 modified := append([]byte{}, line...) 470 modified = replace(modified, match[7], match[7], []byte(info)) 471 if frame.Inline { 472 end := match[7] + len(info) 473 modified = replace(modified, end, end, []byte(" [inline]")) 474 modified = replace(modified, match[2], match[7], []byte(frame.Func)) 475 } 476 symbolized = append(symbolized, modified...) 477 } 478 return symbolized 479 } 480 481 type parsedOpcodes struct { 482 rawBytes []byte 483 decompileFlags DecompilerFlagMask 484 offset int 485 } 486 487 type decompiledOpcodes struct { 488 opcodes []DecompiledOpcode 489 trappingOpcodeIdx int 490 leftBytesCut int 491 } 492 493 // processOpcodes converts a string representation of opcodes used by the Linux kernel into 494 // a sequence of the machine instructions, that surround the one that crashed the kernel. 495 // If the input does not start on a boundary of an instruction, it is attempted to adjust the 496 // strting position. 497 // The method returns an error if it did not manage to correctly decompile the opcodes or 498 // of the decompiled code is not of interest to the reader (e.g. it is a user-space code). 499 func (ctx *linux) processOpcodes(codeSlice string) (*decompiledOpcodes, error) { 500 parsed, err := ctx.parseOpcodes(codeSlice) 501 if err != nil { 502 return nil, err 503 } 504 505 decompiled, err := ctx.decompileWithOffset(parsed) 506 if err != nil { 507 return nil, err 508 } 509 510 if linuxSkipTrapInstrRe.MatchString(decompiled.opcodes[decompiled.trappingOpcodeIdx].Instruction) { 511 // For some reports (like WARNINGs) the trapping instruction is an intentionally 512 // invalid instruction. Decompilation of such code only allows to see the 513 // mechanism, through which the kernel implements such assertions and does not 514 // aid in finding the real issue. 515 return nil, fmt.Errorf("these opcodes are not of interest") 516 } 517 518 return decompiled, nil 519 } 520 521 func (ctx *linux) decompileWithOffset(parsed parsedOpcodes) (*decompiledOpcodes, error) { 522 // It is not guaranteed that the fragment of opcodes starts exactly at the boundary 523 // of a machine instruction. In order to simplify debugging process, we are trying 524 // to find the right starting position. 525 // 526 // We iterate over a fixed number of left boundaries. The exact number of iterations 527 // should strike a balance between the potential usefulness and the extra time needed 528 // to invoke the decompiler. 529 const opcodeAdjustmentLimit = 8 530 531 var bestResult *decompiledOpcodes 532 533 for leftCut := 0; leftCut <= parsed.offset && leftCut < opcodeAdjustmentLimit; leftCut++ { 534 newBytes := parsed.rawBytes[leftCut:] 535 newOffset := parsed.offset - leftCut 536 instructions, err := DecompileOpcodes(newBytes, parsed.decompileFlags, ctx.target) 537 if err != nil { 538 return nil, err 539 } 540 541 // We only want to return the response, where there exists a decoded instruction that 542 // perfectly aligns with the trapping instruction offset. 543 // At the same time, we'll do out best to find a code listing that does not contain 544 // unrecognized (bad) instuctions - this serves as an indicator of a valid result. 545 546 hasBad := false 547 trappingIdx := -1 548 for idx, instruction := range instructions { 549 if instruction.Offset == newOffset { 550 trappingIdx = idx 551 } 552 if instruction.Offset >= newOffset { 553 // Do not take into account instructions after the target offset. Once 554 // decompiler begins to find the right boundary, we cannot improve them. 555 break 556 } 557 hasBad = hasBad || instruction.IsBad 558 } 559 560 if trappingIdx < 0 { 561 continue 562 } 563 564 if !hasBad || bestResult == nil { 565 bestResult = &decompiledOpcodes{ 566 opcodes: instructions, 567 trappingOpcodeIdx: trappingIdx, 568 leftBytesCut: leftCut, 569 } 570 if !hasBad { 571 // The best offset is already found. 572 break 573 } 574 } 575 } 576 if bestResult == nil { 577 return nil, fmt.Errorf("unable to align decompiled code and the trapping instruction offset") 578 } 579 return bestResult, nil 580 } 581 582 func (ctx *linux) parseOpcodes(codeSlice string) (parsedOpcodes, error) { 583 binaryOps := binary.ByteOrder(binary.BigEndian) 584 if ctx.target.LittleEndian { 585 binaryOps = binary.LittleEndian 586 } 587 588 width := 0 589 bytes := []byte{} 590 trapOffset := -1 591 for _, part := range strings.Split(strings.TrimSpace(codeSlice), " ") { 592 if part == "" || len(part)%2 != 0 { 593 return parsedOpcodes{}, fmt.Errorf("invalid opcodes string %#v", part) 594 } 595 596 // Check if this is a marker of a trapping instruction. 597 if part[0] == '(' || part[0] == '<' { 598 if trapOffset >= 0 { 599 return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: multiple trap intructions") 600 } 601 trapOffset = len(bytes) 602 603 if len(part) < 3 { 604 return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: invalid trap opcode") 605 } 606 part = part[1 : len(part)-1] 607 } 608 609 if width == 0 { 610 width = len(part) / 2 611 } 612 613 number, err := strconv.ParseUint(part, 16, 64) 614 if err != nil { 615 return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: failed to parse %#v", part) 616 } 617 618 extraBytes := make([]byte, width) 619 switch len(extraBytes) { 620 case 1: 621 extraBytes[0] = byte(number) 622 case 2: 623 binaryOps.PutUint16(extraBytes, uint16(number)) 624 case 4: 625 binaryOps.PutUint32(extraBytes, uint32(number)) 626 case 8: 627 binaryOps.PutUint64(extraBytes, number) 628 default: 629 return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: invalid width %v", width) 630 } 631 bytes = append(bytes, extraBytes...) 632 } 633 634 if trapOffset < 0 { 635 return parsedOpcodes{}, fmt.Errorf("invalid opcodes string: no trapping instructions") 636 } 637 638 var flags DecompilerFlagMask 639 if ctx.target.Arch == targets.ARM && width == 2 { 640 flags |= FlagForceArmThumbMode 641 } 642 return parsedOpcodes{ 643 rawBytes: bytes, 644 decompileFlags: flags, 645 offset: trapOffset, 646 }, nil 647 } 648 649 // decompileOpcodes detects the most meaningful "Code: " lines from the report, decompiles 650 // them and appends a human-readable listing to the end of the report. 651 func (ctx *linux) decompileOpcodes(text []byte, report *Report) []byte { 652 if report.Type == crash.Hang { 653 // Even though Hang reports do contain the Code: section, there's no point in 654 // decompiling that. So just return the text. 655 return text 656 } 657 // Iterate over all "Code: " lines and pick the first that could be decompiled 658 // that might be of interest to the user. 659 var decompiled *decompiledOpcodes 660 lines := lines(text) 661 for i, line := range lines { 662 var prevLine []byte 663 if i > 0 { 664 prevLine = lines[i-1] 665 } 666 // We want to avoid decompiling code from user-space as it is not of big interest during 667 // debugging kernel problems. 668 // For now this check only works for x86/amd64, but Linux on other architectures supported 669 // by syzkaller does not seem to include user-space code in its oops messages. 670 if linuxUserSegmentRe.Match(prevLine) { 671 continue 672 } 673 match := linuxCodeRe.FindSubmatch(line) 674 if match == nil { 675 continue 676 } 677 decompiledLine, err := ctx.processOpcodes(string(match[1])) 678 if err != nil { 679 continue 680 } 681 decompiled = decompiledLine 682 break 683 } 684 685 if decompiled == nil { 686 return text 687 } 688 689 skipInfo := "" 690 if decompiled.leftBytesCut > 0 { 691 skipInfo = fmt.Sprintf(", %v bytes skipped", decompiled.leftBytesCut) 692 } 693 694 // The decompiled instructions are intentionally put to the bottom of the report instead 695 // being inlined below the corresponding "Code:" line. The intent is to continue to keep 696 // the most important information at the top of the report, so that it is visible from 697 // the syzbot dashboard without scrolling. 698 headLine := fmt.Sprintf("----------------\nCode disassembly (best guess)%v:\n", skipInfo) 699 text = append(text, headLine...) 700 701 for idx, opcode := range decompiled.opcodes { 702 line := opcode.FullDescription 703 if idx == decompiled.trappingOpcodeIdx { 704 line = fmt.Sprintf("*%s <-- trapping instruction\n", line[1:]) 705 } else { 706 line += "\n" 707 } 708 text = append(text, line...) 709 } 710 return text 711 } 712 713 func (ctx *linux) extractGuiltyFile(rep *Report) string { 714 return ctx.extractGuiltyFileRaw(rep.Title, rep.Report[rep.reportPrefixLen:]) 715 } 716 717 func (ctx *linux) extractGuiltyFileRaw(title string, report []byte) string { 718 if strings.HasPrefix(title, "INFO: rcu detected stall") { 719 // Special case for rcu stalls. 720 // There are too many frames that we want to skip before actual guilty frames, 721 // we would need to ignore too many files and that would be fragile. 722 // So instead we try to extract guilty file starting from the known 723 // interrupt entry point first. 724 for _, interruptEnd := range []string{"apic_timer_interrupt+0x", 725 "el1h_64_irq+0x", "Exception stack"} { 726 if pos := bytes.Index(report, []byte(interruptEnd)); pos != -1 { 727 if file := ctx.extractGuiltyFileImpl(report[pos:]); file != "" { 728 return file 729 } 730 } 731 } 732 } 733 return ctx.extractGuiltyFileImpl(report) 734 } 735 736 func (ctx *linux) extractGuiltyFileImpl(report []byte) string { 737 // Extract the first possible guilty file. 738 guilty := "" 739 var line []byte 740 lines := lines(report) 741 for len(lines) > 0 { 742 line, lines = lines[0], lines[1:] 743 match := filenameRe.FindSubmatch(line) 744 if match == nil { 745 continue 746 } 747 file := match[1] 748 if guilty == "" { 749 // Avoid producing no guilty file at all, otherwise we mail the report to nobody. 750 // It's unclear if it's better to return the first one or the last one. 751 // So far the only test we have has only one file anyway. 752 guilty = string(file) 753 } 754 755 if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(line) { 756 continue 757 } 758 guilty = filepath.Clean(string(file)) 759 break 760 } 761 762 // Search for deeper filepaths in the stack trace below the first possible guilty file. 763 deepestPath := filepath.Dir(guilty) 764 for len(lines) > 0 { 765 line, lines = lines[0], lines[1:] 766 match := filenameRe.FindSubmatch(line) 767 if match == nil { 768 continue 769 } 770 file := match[1] 771 if matchesAny(file, ctx.guiltyFileIgnores) || ctx.guiltyLineIgnore.Match(line) { 772 continue 773 } 774 clean := filepath.Clean(string(file)) 775 776 // Check if the new path has *both* the same directory prefix *and* a deeper suffix. 777 if strings.HasPrefix(clean, deepestPath) { 778 suffix := strings.TrimPrefix(clean, deepestPath) 779 if deeperPathRe.Match([]byte(suffix)) { 780 guilty = clean 781 deepestPath = filepath.Dir(guilty) 782 } 783 } 784 } 785 786 return guilty 787 } 788 789 func (ctx *linux) getMaintainers(file string) (vcs.Recipients, error) { 790 if ctx.kernelSrc == "" { 791 return nil, nil 792 } 793 return GetLinuxMaintainers(ctx.kernelSrc, file) 794 } 795 796 func GetLinuxMaintainers(kernelSrc, file string) (vcs.Recipients, error) { 797 mtrs, err := getMaintainersImpl(kernelSrc, file, false) 798 if err != nil { 799 return nil, err 800 } 801 if len(mtrs) <= 1 { 802 mtrs, err = getMaintainersImpl(kernelSrc, file, true) 803 if err != nil { 804 return nil, err 805 } 806 } 807 return mtrs, nil 808 } 809 810 func getMaintainersImpl(kernelSrc, file string, blame bool) (vcs.Recipients, error) { 811 // See #1441 re --git-min-percent. 812 args := []string{"--git-min-percent=15"} 813 if blame { 814 args = append(args, "--git-blame") 815 } 816 args = append(args, "-f", file) 817 script := filepath.FromSlash("scripts/get_maintainer.pl") 818 output, err := osutil.RunCmd(time.Minute, kernelSrc, script, args...) 819 if err != nil { 820 return nil, err 821 } 822 return vcs.ParseMaintainersLinux(output), nil 823 } 824 825 func (ctx *linux) isCorrupted(title string, report []byte, format oopsFormat) (bool, string) { 826 // Check for common title corruptions. 827 for _, re := range linuxCorruptedTitles { 828 if re.MatchString(title) { 829 return true, "title matches corrupted regexp" 830 } 831 } 832 // If the report hasn't matched any of the oops titles, don't mark it as corrupted. 833 if format.title == nil { 834 return false, "" 835 } 836 if format.noStackTrace { 837 return false, "" 838 } 839 // When a report contains 'Call Trace', 'backtrace', 'Allocated' or 'Freed' keywords, 840 // it must also contain at least a single stack frame after each of them. 841 hasStackTrace := false 842 for _, key := range linuxStackParams.stackStartRes { 843 match := key.FindSubmatchIndex(report) 844 if match == nil { 845 continue 846 } 847 frames := lines(report[match[0]:]) 848 if len(frames) < 4 { 849 return true, "call trace is missed" 850 } 851 corrupted := true 852 frames = frames[1:] 853 // Check that at least one of the next few lines contains a frame. 854 outer: 855 for i := 0; i < 15 && i < len(frames); i++ { 856 for _, key1 := range linuxStackParams.stackStartRes { 857 // Next stack trace starts. 858 if key1.Match(frames[i]) { 859 break outer 860 } 861 } 862 if bytes.Contains(frames[i], []byte("(stack is not available)")) || 863 matchesAny(frames[i], linuxStackParams.frameRes) { 864 hasStackTrace = true 865 corrupted = false 866 break 867 } 868 } 869 if corrupted { 870 return true, "no frames in a stack trace" 871 } 872 } 873 if !hasStackTrace { 874 return true, "no stack trace in report" 875 } 876 return false, "" 877 } 878 879 func linuxStallFrameExtractor(frames []string) string { 880 // During rcu stalls and cpu lockups kernel loops in some part of code, 881 // usually across several functions. When the stall is detected, traceback 882 // points to a random stack within the looping code. We generally take 883 // the top function in the stack (with few exceptions) as the bug identity. 884 // As the result stalls with the same root would produce multiple reports 885 // in different functions, which is bad. 886 // Instead we identify a representative function deeper in the stack. 887 // For most syscalls it can be the syscall entry function (e.g. SyS_timer_create). 888 // However, for highly discriminated functions syscalls like ioctl/read/write/connect 889 // we take the previous function (e.g. for connect the one that points to exact 890 // protocol, or for ioctl the one that is related to the device). 891 prev := frames[0] 892 for _, frame := range frames { 893 if matchesAny([]byte(frame), linuxStallAnchorFrames) { 894 if strings.Contains(frame, "smp_call_function") { 895 // In this case we want this function rather than the previous one 896 // (there can be several variations on the next one). 897 prev = "smp_call_function" 898 } 899 return prev 900 } 901 prev = frame 902 } 903 return "" 904 } 905 906 func linuxHangTaskFrameExtractor(frames []string) string { 907 // The problem with task hung reports is that they manifest at random victim stacks, 908 // rather at the root cause stack. E.g. if there is something wrong with RCU subsystem, 909 // we are getting hangs all over the kernel on all synchronize_* calls. 910 // So before resotring to the common logic of skipping some common frames, 911 // we look for 2 common buckets: hangs on synchronize_rcu and hangs on rtnl_lock 912 // and group these together. 913 const synchronizeRCU = "synchronize_rcu" 914 anchorFrames := map[string]string{ 915 "rtnl_lock": "", 916 "synchronize_rcu": synchronizeRCU, 917 "synchronize_srcu": synchronizeRCU, 918 "synchronize_net": synchronizeRCU, 919 "synchronize_sched": synchronizeRCU, 920 } 921 for _, frame := range frames { 922 for anchor, replacement := range anchorFrames { 923 if strings.Contains(frame, anchor) { 924 if replacement != "" { 925 frame = replacement 926 } 927 return frame 928 } 929 } 930 } 931 skip := []string{"sched", "_lock", "_slowlock", "down", "rwsem", "completion", "kthread", 932 "wait", "synchronize", "context_switch", "__switch_to", "cancel_delayed_work", 933 "rcu_barrier"} 934 nextFrame: 935 for _, frame := range frames { 936 for _, ignore := range skip { 937 if strings.Contains(frame, ignore) { 938 continue nextFrame 939 } 940 } 941 return frame 942 } 943 return "" 944 } 945 946 var linuxStallAnchorFrames = []*regexp.Regexp{ 947 // Various generic functions that dispatch work. 948 // We also include some of their callers, so that if some names change 949 // we don't skip whole stacks and proceed parsing the next one. 950 compile("process_one_work"), // workqueue callback 951 compile("do_syscall_"), // syscall entry 952 compile("do_fast_syscall_"), // syscall entry 953 compile("sysenter_dispatch"), // syscall entry 954 compile("tracesys_phase2"), // syscall entry 955 compile("el0_svc_handler"), // syscall entry 956 compile("invoke_syscall"), // syscall entry 957 compile("ret_fast_syscall"), // arm syscall entry 958 compile("netif_receive_skb"), // net receive entry point 959 compile("do_softirq"), 960 compile("call_timer_fn"), 961 compile("_run_timers"), 962 compile("run_timer_softirq"), 963 compile("hrtimer_run"), 964 compile("run_ksoftirqd"), 965 compile("smpboot_thread_fn"), 966 compile("^kthread$"), 967 compile("start_secondary"), 968 compile("cpu_startup_entry"), 969 compile("ret_from_fork"), 970 // Important discriminated syscalls (file_operations callbacks, etc): 971 compile("vfs_write"), 972 compile("vfs_read"), 973 compile("vfs_iter_read"), 974 compile("vfs_iter_write"), 975 compile("do_iter_read"), 976 compile("do_iter_write"), 977 compile("call_read_iter"), 978 compile("call_write_iter"), 979 compile("new_sync_read"), 980 compile("new_sync_write"), 981 compile("vfs_ioctl"), 982 compile("ksys_ioctl"), // vfs_ioctl may be inlined 983 compile("compat_ioctl"), 984 compile("compat_sys_ioctl"), 985 compile("blkdev_driver_ioctl"), 986 compile("blkdev_ioctl"), 987 compile("^call_read_iter"), 988 compile("^call_write_iter"), 989 compile("do_iter_readv_writev"), 990 compile("^call_mmap"), 991 compile("mmap_region"), 992 compile("do_mmap"), 993 compile("do_dentry_open"), 994 compile("vfs_open"), 995 // Socket operations: 996 compile("^sock_sendmsg"), 997 compile("^sock_recvmsg"), 998 compile("^sock_release"), 999 compile("^__sock_release"), 1000 compile("^setsockopt$"), 1001 compile("kernel_setsockopt"), 1002 compile("sock_common_setsockopt"), 1003 compile("^listen$"), 1004 compile("kernel_listen"), 1005 compile("sk_common_release"), 1006 compile("^sock_mmap"), 1007 compile("^accept$"), 1008 compile("kernel_accept"), 1009 compile("^sock_do_ioctl"), 1010 compile("^sock_ioctl"), 1011 compile("^compat_sock_ioctl"), 1012 compile("^nfnetlink_rcv_msg"), 1013 compile("^rtnetlink_rcv_msg"), 1014 compile("^netlink_dump"), 1015 compile("^(sys_)?(socketpair|connect|ioctl)"), 1016 // Page fault entry points: 1017 compile("__do_fault"), 1018 compile("do_page_fault"), 1019 compile("^page_fault$"), 1020 // exit_to_usermode_loop callbacks: 1021 compile("__fput"), 1022 compile("task_work_run"), 1023 compile("exit_to_usermode"), 1024 compile("smp_call_function"), 1025 compile("tasklet_action"), 1026 compile("tasklet_hi_action"), 1027 } 1028 1029 // nolint: lll 1030 var ( 1031 linuxSymbolizeRe = regexp.MustCompile(`(?:\[\<(?:(?:0x)?[0-9a-f]+)\>\])?[ \t]+\(?(?:[0-9]+:)?([a-zA-Z0-9_.]+)\+0x([0-9a-f]+)/0x([0-9a-f]+)\)?`) 1032 linuxRipFrame = compile(`(?:IP|NIP|pc |PC is at):? (?:(?:[0-9]+:)?(?:{{PC}} +){0,2}{{FUNC}}|(?:[0-9]+:)?0x[0-9a-f]+|(?:[0-9]+:)?{{PC}} +\[< *\(null\)>\] +\(null\)|[0-9]+: +\(null\))`) 1033 linuxCallTrace = compile(`(?:Call (?:T|t)race:)|(?:Backtrace:)`) 1034 linuxCodeRe = regexp.MustCompile(`(?m)^\s*Code\:\s+((?:[A-Fa-f0-9\(\)\<\>]{2,8}\s*)*)\s*$`) 1035 linuxSkipTrapInstrRe = regexp.MustCompile(`^ud2|brk\s+#0x800$`) 1036 linuxUserSegmentRe = regexp.MustCompile(`^RIP:\s+0033:`) 1037 ) 1038 1039 var linuxCorruptedTitles = []*regexp.Regexp{ 1040 // Sometimes timestamps get merged into the middle of report description. 1041 regexp.MustCompile(`\[ *[0-9]+\.[0-9]+\]`), 1042 } 1043 1044 var linuxStackParams = &stackParams{ 1045 stackStartRes: []*regexp.Regexp{ 1046 regexp.MustCompile(`Call (?:T|t)race`), 1047 regexp.MustCompile(`Allocated:`), 1048 regexp.MustCompile(`Allocated by task [0-9]+:`), 1049 regexp.MustCompile(`Freed:`), 1050 regexp.MustCompile(`Freed by task [0-9]+:`), 1051 // Match 'backtrace:', but exclude 'stack backtrace:' 1052 regexp.MustCompile(`[^k] backtrace:`), 1053 regexp.MustCompile(`Backtrace:`), 1054 regexp.MustCompile(`Uninit was stored to memory at`), 1055 }, 1056 frameRes: []*regexp.Regexp{ 1057 compile("^ *(?:{{PC}} ){0,2}{{FUNC}}"), 1058 // Arm is totally different. 1059 // Extract both current and next frames. This is needed for the top 1060 // frame which is present only in LR register which we don't parse. 1061 compile(`^ *{{PC}} \(([a-zA-Z0-9_.]+)\) from {{PC}} \({{FUNC}}`), 1062 }, 1063 skipPatterns: []string{ 1064 "__sanitizer", 1065 "__asan", 1066 "kasan", 1067 "__msan", 1068 "kmsan", 1069 "kcsan_setup_watchpoint", 1070 "check_memory_region", 1071 "check_heap_object", 1072 "check_object", 1073 "read_word_at_a_time", 1074 "(read|write)_once_.*nocheck", 1075 "print_address_description", 1076 "panic", 1077 "invalid_op", 1078 "report_bug", 1079 "fixup_bug", 1080 "print_report", 1081 "print_usage_bug", 1082 "do_error", 1083 "invalid_op", 1084 `_trap$|do_trap`, 1085 "show_stack", 1086 "dump_stack", 1087 "walk_stack", 1088 "dump_backtrace", 1089 "warn_slowpath", 1090 "warn_alloc", 1091 "warn_bogus", 1092 "__warn", 1093 "alloc_page", 1094 "k?v?(?:m|z|c)alloc", 1095 "krealloc", 1096 "kmem_cache", 1097 "allocate_slab", 1098 "folio_alloc", 1099 "filemap_alloc_folio", 1100 "__filemap_get_folio", 1101 "find_or_create_page", 1102 "do_read_cache_folio", 1103 "read_cache_page", 1104 "pagecache_get_page", 1105 "grab_cache_page_write_begin", 1106 "slab_", 1107 "debug_object", 1108 "timer_is_static_object", 1109 "work_is_static_object", 1110 "__might_fault", 1111 "print_unlock", 1112 "imbalance_bug", 1113 "lockdep", 1114 "bh_enable", 1115 "bh_disable", 1116 "perf_trace", 1117 "lock_acquire", 1118 "lock_release", 1119 "lock_class", 1120 "mark_lock", 1121 "(reacquire|mark)_held_locks", 1122 "raw_spin_rq", 1123 "spin_lock", 1124 "spin_trylock", 1125 "spin_unlock", 1126 "read_lock", 1127 "read_trylock", 1128 "write_lock", 1129 "write_trylock", 1130 "read_unlock", 1131 "write_unlock", 1132 "^down$", 1133 "down_read", 1134 "down_write", 1135 "down_read_trylock", 1136 "down_write_trylock", 1137 "down_trylock", 1138 "up_read", 1139 "up_write", 1140 "^mutex_", 1141 "^__mutex_", 1142 "^rt_mutex_", 1143 "owner_on_cpu", 1144 "osq_lock", 1145 "osq_unlock", 1146 "atomic(64)?_(dec|inc|read|set|or|xor|and|add|sub|fetch|xchg|cmpxchg|try)", 1147 "(set|clear|change|test)_bit", 1148 "__wake_up", 1149 "^refcount_", 1150 "^kref_", 1151 "ref_tracker", 1152 "seqprop_assert", 1153 "memcpy", 1154 "memcmp", 1155 "memset", 1156 "memchr", 1157 "memmove", 1158 "memdup", 1159 "strcmp", 1160 "strncmp", 1161 "strcpy", 1162 "strlcpy", 1163 "strncpy", 1164 "strscpy", 1165 "strlen", 1166 "strstr", 1167 "strnstr", 1168 "strnlen", 1169 "strchr", 1170 "strdup", 1171 "strndup", 1172 "copy_to_user", 1173 "copy_from_user", 1174 "copy_to_iter", 1175 "copy_from_iter", 1176 "copy_page_to_iter", 1177 "copy_page_from_iter", 1178 "copy_folio_to_iter", 1179 "^copyin$", 1180 "^copyout$", 1181 "put_user", 1182 "get_user", 1183 "might_fault", 1184 "might_sleep", 1185 "list_add", 1186 "list_del", 1187 "list_replace", 1188 "list_move", 1189 "list_splice", 1190 "^rb_", 1191 "^__rb_", 1192 "_indirect_thunk_", // retpolines 1193 "string", 1194 "pointer", 1195 "snprintf", 1196 "scnprintf", 1197 "kasprintf", 1198 "kvasprintf", 1199 "printk", 1200 "va_format", 1201 "dev_info", 1202 "dev_notice", 1203 "dev_warn", 1204 "dev_err", 1205 "dev_alert", 1206 "dev_crit", 1207 "dev_emerg", 1208 "program_check_exception", 1209 "program_check_common", 1210 "del_timer", 1211 "flush_work", 1212 "__cancel_work_timer", 1213 "cancel_work_sync", 1214 "try_to_grab_pending", 1215 "flush_workqueue", 1216 "drain_workqueue", 1217 "destroy_workqueue", 1218 "queue_work", 1219 "finish_wait", 1220 "kthread_stop", 1221 "kobject_", 1222 "add_uevent_var", 1223 "get_device_parent", 1224 "device_add", 1225 "device_del", 1226 "device_unregister", 1227 "device_destroy", 1228 "device_release", 1229 "devres_release_all", 1230 "hwrng_unregister", 1231 "i2c_del_adapter", 1232 "__unregister_client", 1233 "device_for_each_child", 1234 "rollback_registered", 1235 "unregister_netdev", 1236 "sysfs_remove", 1237 "device_remove_file", 1238 "tty_unregister_device", 1239 "dummy_urb_enqueue", 1240 "usb_kill_urb", 1241 "usb_kill_anchored_urbs", 1242 "usb_control_msg", 1243 "usb_hcd_submit_urb", 1244 "usb_submit_urb", 1245 "^complete$", 1246 "wait_for_completion", 1247 "^kv?free$", 1248 "kfree_skb", 1249 "readb$", 1250 "readw$", 1251 "readl$", 1252 "readq$", 1253 "writeb$", 1254 "writew$", 1255 "writel$", 1256 "writeq$", 1257 "logic_in", 1258 "logic_out", 1259 "^crc\\d+", 1260 "crc_itu_t", 1261 "__might_resched", 1262 "assertfail", 1263 "^iput$", 1264 "^iput_final$", 1265 "^ihold$", 1266 "hex_dump_to_buffer", 1267 "print_hex_dump", 1268 "^klist_", 1269 "(trace|lockdep)_(hard|soft)irq", 1270 "^(un)?lock_page", 1271 "stack_trace_consume_entry", 1272 "arch_stack_walk", 1273 "stack_trace_save", 1274 "insert_work", 1275 "__queue_delayed_work", 1276 "queue_delayed_work_on", 1277 "ida_free", 1278 // arm64 translation exception handling path. 1279 "do_(kernel|translation)_fault", 1280 "do_mem_abort", 1281 "el1_abort", 1282 "el1h_64_sync(?:_handler)?", 1283 "print_tainted", 1284 "xas_(?:start|load|find)", 1285 "find_lock_entries", 1286 "truncate_inode_pages_range", 1287 "__phys_addr", 1288 }, 1289 corruptedLines: []*regexp.Regexp{ 1290 // Fault injection stacks are frequently intermixed with crash reports. 1291 // Note: the actual symbol can have all kinds of weird suffixes like ".isra.7", ".cold" or ".isra.56.cold.74". 1292 compile(`^( \[\<?(?:0x)?[0-9a-f]+\>?\])? should_fail(slab)?(\.[a-z0-9.]+)?\+0x`), 1293 }, 1294 stripFramePrefixes: []string{ 1295 "SYSC_", 1296 "SyS_", 1297 "sys_", 1298 "__x64_", 1299 "__ia32_", 1300 "__arm64_", 1301 "____sys_", 1302 "___sys_", 1303 "__sys_", 1304 "__se_", 1305 "__do_sys_", 1306 "compat_SYSC_", 1307 "compat_SyS_", 1308 "ksys_", 1309 }, 1310 } 1311 1312 func warningStackFmt(skip ...string) *stackFmt { 1313 return &stackFmt{ 1314 // In newer kernels WARNING traps and actual stack starts after invalid_op frame, 1315 // older kernels just print stack. 1316 parts: []*regexp.Regexp{ 1317 // x86_64 warning stack starts with "RIP:" line, 1318 // while powerpc64 starts with "--- interrupt:". 1319 compile("(?:" + linuxRipFrame.String() + "|--- interrupt: [0-9]+ at {{FUNC}})"), 1320 parseStackTrace, 1321 }, 1322 parts2: []*regexp.Regexp{ 1323 linuxCallTrace, 1324 parseStackTrace, 1325 }, 1326 skip: skip, 1327 } 1328 } 1329 1330 // nolint: lll 1331 var linuxOopses = append([]*oops{ 1332 { 1333 []byte("BUG:"), 1334 []oopsFormat{ 1335 { 1336 title: compile("BUG: KASAN:"), 1337 report: compile("BUG: KASAN: ([a-z\\-]+) in {{FUNC}}(?:.*\\n)+?.*(Read|Write) (?:of size|at addr) (?:[0-9a-f]+)"), 1338 fmt: "KASAN: %[1]v %[3]v in %[4]v", 1339 alt: []string{"bad-access in %[4]v"}, 1340 stack: &stackFmt{ 1341 parts: []*regexp.Regexp{ 1342 compile("BUG: KASAN: (?:[a-z\\-]+) in {{FUNC}}"), 1343 linuxCallTrace, 1344 parseStackTrace, 1345 }, 1346 // These frames are present in KASAN_HW_TAGS reports. 1347 skip: []string{"kernel_fault", "tag_check", "mem_abort", "^el1_", "^el1h_"}, 1348 }, 1349 reportType: crash.KASAN, 1350 }, 1351 { 1352 title: compile("BUG: KASAN:"), 1353 report: compile("BUG: KASAN: (?:double-free or invalid-free|double-free|invalid-free) in {{FUNC}}"), 1354 fmt: "KASAN: invalid-free in %[2]v", 1355 alt: []string{"invalid-free in %[2]v"}, 1356 stack: &stackFmt{ 1357 parts: []*regexp.Regexp{ 1358 compile("BUG: KASAN: (?:double-free or invalid-free|double-free|invalid-free) in {{FUNC}}"), 1359 linuxCallTrace, 1360 parseStackTrace, 1361 }, 1362 skip: []string{"slab_", "kfree", "vunmap", "vfree"}, 1363 }, 1364 reportType: crash.KASAN, 1365 }, 1366 { 1367 title: compile("BUG: KASAN: ([a-z\\-]+) on address(?:.*\\n)+?.*(Read|Write) of size ([0-9]+)"), 1368 fmt: "KASAN: %[1]v %[2]v", 1369 reportType: crash.KASAN, 1370 }, 1371 { 1372 title: compile("BUG: KASAN: (.*)"), 1373 fmt: "KASAN: %[1]v", 1374 corrupted: true, 1375 reportType: crash.KASAN, 1376 }, 1377 { 1378 title: compile("BUG: KMSAN: kernel-usb-infoleak"), 1379 report: compile("BUG: KMSAN: kernel-usb-infoleak in {{FUNC}}"), 1380 fmt: "KMSAN: kernel-usb-infoleak in %[2]v", 1381 alt: []string{"KMSAN origin in %[3]v"}, 1382 stack: &stackFmt{ 1383 parts: []*regexp.Regexp{ 1384 parseStackTrace, 1385 compile("(Local variable .* created at:|Uninit was created at:)"), 1386 parseStackTrace, 1387 }, 1388 skip: []string{"alloc_skb", "usb_submit_urb", "usb_start_wait_urb", "usb_bulk_msg", "usb_interrupt_msg", "usb_control_msg"}, 1389 }, 1390 noStackTrace: true, 1391 }, 1392 { 1393 title: compile("BUG: KMSAN:"), 1394 report: compile("BUG: KMSAN: ([a-z\\-]+) in {{FUNC}}"), 1395 fmt: "KMSAN: %[1]v in %[3]v", 1396 alt: []string{ 1397 "bad-access in %[3]v", 1398 }, 1399 stack: &stackFmt{ 1400 parts: []*regexp.Regexp{ 1401 parseStackTrace, 1402 compile("(Local variable .* created at:|Uninit was created at:)"), 1403 parseStackTrace, 1404 }, 1405 skip: []string{"alloc_skb", "netlink_ack", "netlink_rcv_skb"}, 1406 }, 1407 noStackTrace: true, 1408 }, 1409 { 1410 title: compile("BUG: KCSAN: data-race"), 1411 report: compile("BUG: KCSAN: (.*)"), 1412 fmt: "KCSAN: %[1]v", 1413 noStackTrace: true, 1414 reportType: crash.DataRace, 1415 }, 1416 { 1417 title: compile("BUG: KCSAN:"), 1418 report: compile("BUG: KCSAN: (.*)"), 1419 fmt: "KCSAN: %[1]v", 1420 noStackTrace: true, 1421 }, 1422 { 1423 title: compile("BUG: KFENCE: (use-after-free|out-of-bounds) ([a-z\\-]+) in {{FUNC}}"), 1424 fmt: "KFENCE: %[1]v in %[4]v", 1425 alt: []string{"bad-access in %[4]v"}, 1426 stack: &stackFmt{ 1427 parts: []*regexp.Regexp{ 1428 compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"), 1429 parseStackTrace, 1430 }, 1431 }, 1432 }, 1433 { 1434 title: compile("BUG: KFENCE: invalid free in {{FUNC}}"), 1435 fmt: "KFENCE: invalid free in %[2]v", 1436 alt: []string{"invalid-free in %[2]v"}, 1437 noStackTrace: true, 1438 stack: &stackFmt{ 1439 parts: []*regexp.Regexp{ 1440 compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"), 1441 parseStackTrace, 1442 }, 1443 }, 1444 }, 1445 { 1446 title: compile("BUG: KFENCE: invalid (read|write) in {{FUNC}}"), 1447 fmt: "KFENCE: invalid %[1]v in %[3]v", 1448 alt: []string{"bad-access in %[3]v"}, 1449 stack: &stackFmt{ 1450 parts: []*regexp.Regexp{ 1451 compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"), 1452 parseStackTrace, 1453 }, 1454 }, 1455 }, 1456 { 1457 title: compile("BUG: KFENCE: memory corruption in {{FUNC}}"), 1458 fmt: "KFENCE: memory corruption in %[2]v", 1459 noStackTrace: true, 1460 stack: &stackFmt{ 1461 parts: []*regexp.Regexp{ 1462 compile("BUG: KFENCE: (?:[a-z\\- ]+) in {{FUNC}}"), 1463 parseStackTrace, 1464 }, 1465 }, 1466 }, 1467 { 1468 title: compile("BUG: (?:unable to handle kernel paging request|unable to handle page fault for address|Unable to handle kernel data access)"), 1469 fmt: "BUG: unable to handle kernel paging request in %[1]v", 1470 alt: []string{"bad-access in %[1]v"}, 1471 stack: &stackFmt{ 1472 parts: []*regexp.Regexp{ 1473 linuxRipFrame, 1474 linuxCallTrace, 1475 parseStackTrace, 1476 }, 1477 }, 1478 }, 1479 { 1480 title: compile("BUG: (?:unable to handle kernel NULL pointer dereference|kernel NULL pointer dereference|Kernel NULL pointer dereference)"), 1481 fmt: "BUG: unable to handle kernel NULL pointer dereference in %[1]v", 1482 alt: []string{"bad-access in %[1]v"}, 1483 stack: &stackFmt{ 1484 parts: []*regexp.Regexp{ 1485 linuxRipFrame, 1486 linuxCallTrace, 1487 parseStackTrace, 1488 }, 1489 }, 1490 }, 1491 { 1492 // Sometimes with such BUG failures, the second part of the header doesn't get printed 1493 // or gets corrupted, because kernel prints it as two separate printk() calls. 1494 title: compile("BUG: (?:unable to handle kernel|Unable to handle kernel)"), 1495 fmt: "BUG: unable to handle kernel", 1496 corrupted: true, 1497 }, 1498 { 1499 title: compile("BUG: (spinlock|rwlock) (lockup suspected|already unlocked|recursion" + 1500 "|cpu recursion|bad magic|wrong owner|wrong CPU|trylock failure on UP)"), 1501 fmt: "BUG: %[1]v %[2]v in %[3]v", 1502 stack: &stackFmt{ 1503 parts: []*regexp.Regexp{ 1504 linuxCallTrace, 1505 parseStackTrace, 1506 }, 1507 skip: []string{"spin_", "_lock", "_unlock"}, 1508 }, 1509 reportType: crash.LockdepBug, 1510 }, 1511 { 1512 title: compile("BUG: soft lockup"), 1513 fmt: "BUG: soft lockup in %[1]v", 1514 alt: []string{"stall in %[1]v"}, 1515 stack: &stackFmt{ 1516 parts: []*regexp.Regexp{ 1517 linuxRipFrame, 1518 linuxCallTrace, 1519 parseStackTrace, 1520 }, 1521 extractor: linuxStallFrameExtractor, 1522 }, 1523 reportType: crash.Hang, 1524 }, 1525 { 1526 title: compile("BUG: .*still has locks held!"), 1527 report: compile("BUG: .*still has locks held!(?:.*\\n)+?.*{{PC}} +{{FUNC}}"), 1528 fmt: "BUG: still has locks held in %[1]v", 1529 reportType: crash.LockdepBug, 1530 }, 1531 { 1532 title: compile("BUG: scheduling while atomic"), 1533 fmt: "BUG: scheduling while atomic in %[1]v", 1534 stack: &stackFmt{ 1535 parts: []*regexp.Regexp{ 1536 linuxCallTrace, 1537 parseStackTrace, 1538 }, 1539 skip: []string{"schedule"}, 1540 }, 1541 reportType: crash.AtomicSleep, 1542 }, 1543 { 1544 title: compile("BUG: lock held when returning to user space"), 1545 report: compile("BUG: lock held when returning to user space(?:.*\\n)+?.*leaving the kernel with locks still held(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"), 1546 fmt: "BUG: lock held when returning to user space in %[1]v", 1547 noStackTrace: true, 1548 }, 1549 { 1550 title: compile("BUG: bad unlock balance detected!"), 1551 fmt: "BUG: bad unlock balance in %[1]v", 1552 stack: &stackFmt{ 1553 parts: []*regexp.Regexp{ 1554 compile("{{PC}} +{{FUNC}}"), 1555 linuxCallTrace, 1556 parseStackTrace, 1557 }, 1558 }, 1559 reportType: crash.LockdepBug, 1560 }, 1561 { 1562 title: compile("BUG: held lock freed!"), 1563 report: compile("BUG: held lock freed!(?:.*\\n)+?.*{{PC}} +{{FUNC}}"), 1564 fmt: "BUG: held lock freed in %[1]v", 1565 reportType: crash.LockdepBug, 1566 }, 1567 { 1568 title: compile("BUG: Bad rss-counter state"), 1569 fmt: "BUG: Bad rss-counter state", 1570 noStackTrace: true, 1571 }, 1572 { 1573 title: compile("BUG: non-zero nr_ptes on freeing mm"), 1574 fmt: "BUG: non-zero nr_ptes on freeing mm", 1575 noStackTrace: true, 1576 }, 1577 { 1578 title: compile("BUG: non-zero nr_pmds on freeing mm"), 1579 fmt: "BUG: non-zero nr_pmds on freeing mm", 1580 noStackTrace: true, 1581 }, 1582 { 1583 // Kernel includes filesystem type and block device name into the message. 1584 // We used to include them, but block devices are plain harmful (loop0/1/2), 1585 // and filesystem type also leads to duplicates. So now we exclude them. 1586 title: compile("BUG: Dentry .* still in use"), 1587 report: compile("BUG: Dentry .* still in use \\([0-9]+\\) \\[(unmount) of ([^\\]]+)\\]"), 1588 fmt: "BUG: Dentry still in use in %[1]v", 1589 alt: []string{"BUG: Dentry still in use [%[1]v of %[2]v]"}, 1590 }, 1591 { 1592 title: compile("BUG: Bad page state"), 1593 fmt: "BUG: Bad page state", 1594 }, 1595 { 1596 title: compile("BUG: Bad page map"), 1597 fmt: "BUG: Bad page map", 1598 }, 1599 { 1600 title: compile("BUG: workqueue lockup"), 1601 fmt: "BUG: workqueue lockup", 1602 noStackTrace: true, 1603 }, 1604 { 1605 title: compile("BUG: sleeping function called from invalid context at (.*)"), 1606 fmt: "BUG: sleeping function called from invalid context in %[2]v", 1607 stack: &stackFmt{ 1608 parts: []*regexp.Regexp{ 1609 linuxCallTrace, 1610 parseStackTrace, 1611 }, 1612 }, 1613 reportType: crash.AtomicSleep, 1614 }, 1615 { 1616 title: compile("BUG: using ([a-z_]+)\\(\\) in preemptible"), 1617 fmt: "BUG: using %[1]v() in preemptible code in %[2]v", 1618 stack: &stackFmt{ 1619 parts: []*regexp.Regexp{ 1620 linuxCallTrace, 1621 parseStackTrace, 1622 }, 1623 skip: []string{"dump_stack", "preemption", "preempt", "debug_", 1624 "processor_id", "this_cpu"}, 1625 }, 1626 }, 1627 { 1628 title: compile("BUG: workqueue leaked lock or atomic"), 1629 report: compile("BUG: workqueue leaked lock or atomic(?:.*\\n)+?" + 1630 ".*last function: ([a-zA-Z0-9_]+)\\n"), 1631 fmt: "BUG: workqueue leaked lock or atomic in %[1]v", 1632 noStackTrace: true, 1633 }, 1634 { 1635 title: compile("BUG: memory leak"), 1636 fmt: "memory leak in %[1]v", 1637 stack: &stackFmt{ 1638 parts: []*regexp.Regexp{ 1639 compile("backtrace:"), 1640 parseStackTrace, 1641 }, 1642 skip: []string{"kmemleak", "mmap", "kmem", "slab", "alloc", "create_object", 1643 "idr_get", "list_lru_init", "kasprintf", "kvasprintf", 1644 "pcpu_create", "strdup", "strndup", "memdup"}, 1645 }, 1646 reportType: crash.MemoryLeak, 1647 }, 1648 { 1649 title: compile("BUG: .*stack guard page was hit at"), 1650 fmt: "BUG: stack guard page was hit in %[1]v", 1651 alt: []string{"stack-overflow in %[1]v"}, 1652 stack: &stackFmt{ 1653 parts: []*regexp.Regexp{ 1654 linuxRipFrame, 1655 linuxCallTrace, 1656 parseStackTrace, 1657 }, 1658 extractor: linuxStallFrameExtractor, 1659 }, 1660 reportType: unspecifiedType, // This is a printk(), not a BUG_ON(). 1661 }, 1662 { 1663 title: compile("BUG: Invalid wait context"), 1664 // Somehow amd64 and arm/arm64 report this bug completely differently. 1665 // This is arm/arm64 format, but we match amd64 title to not duplicate bug reports. 1666 fmt: "WARNING: locking bug in %[1]v", 1667 stack: &stackFmt{ 1668 parts: []*regexp.Regexp{ 1669 linuxCallTrace, 1670 parseStackTrace, 1671 }, 1672 skip: []string{"lock_sock", "release_sock"}, 1673 }, 1674 reportType: crash.LockdepBug, 1675 }, 1676 { 1677 title: compile(`BUG:[[:space:]]*(?:\n|$)`), 1678 fmt: "BUG: corrupted", 1679 corrupted: true, 1680 }, 1681 }, 1682 []*regexp.Regexp{ 1683 // CONFIG_DEBUG_OBJECTS output. 1684 compile("ODEBUG:"), 1685 // Android prints this sometimes during boot. 1686 compile("Boot_DEBUG:"), 1687 compile("xlog_status:"), 1688 // Android ART debug output. 1689 compile("DEBUG:"), 1690 // pkg/host output in debug mode. 1691 compile("BUG: no syscalls can create resource"), 1692 }, 1693 crash.UnknownType, 1694 }, 1695 { 1696 []byte("WARNING:"), 1697 []oopsFormat{ 1698 { 1699 title: compile("WARNING: .*lib/debugobjects\\.c.* (?:debug_print|debug_check)"), 1700 fmt: "WARNING: ODEBUG bug in %[1]v", 1701 // Skip all users of ODEBUG as well. 1702 stack: warningStackFmt("debug_", "rcu", "hrtimer_", "timer_", 1703 "work_", "percpu_", "vunmap", 1704 "vfree", "__free_", "debug_check", "kobject_"), 1705 }, 1706 { 1707 title: compile("WARNING: .*mm/usercopy\\.c.* usercopy_warn"), 1708 fmt: "WARNING: bad usercopy in %[1]v", 1709 stack: warningStackFmt("usercopy", "__check"), 1710 }, 1711 { 1712 title: compile("WARNING: .*lib/kobject\\.c.* kobject_"), 1713 fmt: "WARNING: kobject bug in %[1]v", 1714 stack: warningStackFmt("kobject_"), 1715 }, 1716 { 1717 title: compile("WARNING: .*fs/proc/generic\\.c.* proc_register"), 1718 fmt: "WARNING: proc registration bug in %[1]v", 1719 stack: warningStackFmt("proc_"), 1720 }, 1721 { 1722 title: compile("WARNING: .*lib/refcount\\.c.* refcount_"), 1723 fmt: "WARNING: refcount bug in %[1]v", 1724 stack: warningStackFmt("refcount", "kobject_"), 1725 }, 1726 { 1727 title: compile("WARNING: .*kernel/locking/lockdep\\.c.*lock_"), 1728 fmt: "WARNING: locking bug in %[1]v", 1729 stack: warningStackFmt("lock_sock", "release_sock"), 1730 reportType: crash.LockdepBug, 1731 }, 1732 { 1733 title: compile("WARNING: .*still has locks held!"), 1734 report: compile("WARNING: .*still has locks held!(?:.*\\n)+?.*at: {{FUNC}}"), 1735 fmt: "WARNING: still has locks held in %[1]v", 1736 reportType: crash.LockdepBug, 1737 }, 1738 { 1739 title: compile("WARNING: Nested lock was not taken"), 1740 fmt: "WARNING: nested lock was not taken in %[1]v", 1741 stack: warningStackFmt(), 1742 reportType: crash.LockdepBug, 1743 }, 1744 { 1745 title: compile("WARNING: lock held when returning to user space"), 1746 report: compile("WARNING: lock held when returning to user space(?:.*\\n)+?.*leaving the kernel with locks still held(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"), 1747 fmt: "WARNING: lock held when returning to user space in %[1]v", 1748 noStackTrace: true, 1749 reportType: crash.LockdepBug, 1750 }, 1751 { 1752 title: compile("WARNING: .*mm/.*\\.c.* k?.?malloc"), 1753 fmt: "WARNING: kmalloc bug in %[1]v", 1754 stack: warningStackFmt("kmalloc", "krealloc", "slab", "kmem"), 1755 }, 1756 { 1757 title: compile("WARNING: .*mm/vmalloc.c.*__vmalloc_node"), 1758 fmt: "WARNING: zero-size vmalloc in %[1]v", 1759 stack: warningStackFmt(), 1760 }, 1761 { 1762 title: compile("WARNING: .* usb_submit_urb"), 1763 fmt: "WARNING in %[1]v/usb_submit_urb", 1764 stack: warningStackFmt("usb_submit_urb", "usb_start_wait_urb", "usb_bulk_msg", "usb_interrupt_msg", "usb_control_msg"), 1765 }, 1766 { 1767 title: compile("WARNING: .* at {{SRC}} {{FUNC}}"), 1768 fmt: "WARNING in %[3]v", 1769 stack: warningStackFmt(), 1770 }, 1771 { 1772 title: compile("WARNING: possible circular locking dependency detected"), 1773 report: compile("WARNING: possible circular locking dependency detected(?:.*\\n)+?.*is trying to acquire lock"), 1774 fmt: "possible deadlock in %[1]v", 1775 stack: &stackFmt{ 1776 parts: []*regexp.Regexp{ 1777 compile("at: (?:{{PC}} +)?{{FUNC}}"), 1778 compile("at: (?:{{PC}} +)?{{FUNC}}"), 1779 parseStackTrace, 1780 }, 1781 // These workqueue functions take locks associated with work items. 1782 // All deadlocks observed in these functions are 1783 // work-item-subsystem-related. 1784 skip: []string{"process_one_work", "flush_workqueue", 1785 "drain_workqueue", "destroy_workqueue"}, 1786 }, 1787 reportType: crash.LockdepBug, 1788 }, 1789 { 1790 title: compile("WARNING: possible irq lock inversion dependency detected"), 1791 report: compile("WARNING: possible irq lock inversion dependency detected(?:.*\\n)+?.*just changed the state of lock(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"), 1792 fmt: "possible deadlock in %[1]v", 1793 reportType: crash.LockdepBug, 1794 }, 1795 { 1796 title: compile("WARNING: .*-safe -> .*-unsafe lock order detected"), 1797 fmt: "possible deadlock in %[1]v", 1798 stack: &stackFmt{ 1799 parts: []*regexp.Regexp{ 1800 compile("which became (?:.*) at:"), 1801 parseStackTrace, 1802 }, 1803 }, 1804 reportType: crash.LockdepBug, 1805 }, 1806 { 1807 title: compile("WARNING: possible recursive locking detected"), 1808 report: compile("WARNING: possible recursive locking detected(?:.*\\n)+?.*is trying to acquire lock(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"), 1809 fmt: "possible deadlock in %[1]v", 1810 reportType: crash.LockdepBug, 1811 }, 1812 { 1813 title: compile("WARNING: inconsistent lock state"), 1814 report: compile("WARNING: inconsistent lock state(?:.*\\n)+?.*takes(?:.*\\n)+?.*at: (?:{{PC}} +)?{{FUNC}}"), 1815 fmt: "inconsistent lock state in %[2]v", 1816 stack: &stackFmt{ 1817 parts: []*regexp.Regexp{ 1818 linuxCallTrace, 1819 parseStackTrace, 1820 }, 1821 }, 1822 reportType: crash.LockdepBug, 1823 }, 1824 { 1825 title: compile("WARNING: suspicious RCU usage"), 1826 report: compile("WARNING: suspicious RCU usage(?:.*\n)+?.*?{{SRC}}"), 1827 fmt: "WARNING: suspicious RCU usage in %[2]v", 1828 stack: &stackFmt{ 1829 parts: []*regexp.Regexp{ 1830 linuxCallTrace, 1831 parseStackTrace, 1832 }, 1833 skip: []string{"rcu", "kmem", "slab"}, 1834 }, 1835 reportType: crash.LockdepBug, 1836 }, 1837 { 1838 title: compile("WARNING: kernel stack regs at [0-9a-f]+ in [^ ]* has bad '([^']+)' value"), 1839 fmt: "WARNING: kernel stack regs has bad '%[1]v' value", 1840 noStackTrace: true, 1841 reportType: unspecifiedType, // This is printk(). 1842 }, 1843 { 1844 title: compile("WARNING: kernel stack frame pointer at [0-9a-f]+ in [^ ]* has bad value"), 1845 fmt: "WARNING: kernel stack frame pointer has bad value", 1846 noStackTrace: true, 1847 reportType: unspecifiedType, // This is printk(). 1848 }, 1849 { 1850 title: compile("WARNING: bad unlock balance detected!"), 1851 fmt: "WARNING: bad unlock balance in %[1]v", 1852 stack: &stackFmt{ 1853 parts: []*regexp.Regexp{ 1854 compile("{{PC}} +{{FUNC}}"), 1855 linuxCallTrace, 1856 parseStackTrace, 1857 }, 1858 }, 1859 reportType: crash.LockdepBug, 1860 }, 1861 { 1862 title: compile("WARNING: held lock freed!"), 1863 report: compile("WARNING: held lock freed!(?:.*\\n)+?.*at:(?: {{PC}})? +{{FUNC}}"), 1864 fmt: "WARNING: held lock freed in %[1]v", 1865 reportType: crash.LockdepBug, 1866 }, 1867 { 1868 title: compile("WARNING: kernel stack regs .* has bad 'bp' value"), 1869 fmt: "WARNING: kernel stack regs has bad value", 1870 noStackTrace: true, 1871 reportType: unspecifiedType, // This is printk(). 1872 }, 1873 { 1874 title: compile("WARNING: kernel stack frame pointer .* has bad value"), 1875 fmt: "WARNING: kernel stack regs has bad value", 1876 noStackTrace: true, 1877 reportType: unspecifiedType, // This is printk(). 1878 }, 1879 { 1880 title: compile(`WARNING:[[:space:]]*(?:\n|$)`), 1881 fmt: "WARNING: corrupted", 1882 corrupted: true, 1883 reportType: unspecifiedType, // This is printk(). 1884 }, 1885 }, 1886 []*regexp.Regexp{ 1887 compile("WARNING: /etc/ssh/moduli does not exist, using fixed modulus"), // printed by sshd 1888 compile("WARNING: workqueue cpumask: online intersect > possible intersect"), 1889 compile("WARNING: [Tt]he mand mount option"), 1890 compile("WARNING: Unsupported flag value\\(s\\) of 0x%x in DT_FLAGS_1"), // printed when glibc is dumped 1891 compile("WARNING: Unprivileged eBPF is enabled with eIBRS"), 1892 compile(`WARNING: fbcon: Driver '(.*)' missed to adjust virtual screen size (\((?:\d+)x(?:\d+) vs\. (?:\d+)x(?:\d+)\))`), 1893 compile(`WARNING: See https.* for mitigation options.`), 1894 compile(`WARNING: kernel not compiled with CPU_SRSO`), 1895 }, 1896 crash.Warning, 1897 }, 1898 { 1899 []byte("INFO:"), 1900 []oopsFormat{ 1901 { 1902 title: compile("INFO: possible circular locking dependency detected"), 1903 report: compile("INFO: possible circular locking dependency detected \\](?:.*\\n)+?.*is trying to acquire lock(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"), 1904 fmt: "possible deadlock in %[1]v", 1905 reportType: crash.LockdepBug, 1906 }, 1907 { 1908 title: compile("INFO: possible irq lock inversion dependency detected"), 1909 report: compile("INFO: possible irq lock inversion dependency detected \\](?:.*\\n)+?.*just changed the state of lock(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"), 1910 fmt: "possible deadlock in %[1]v", 1911 reportType: crash.LockdepBug, 1912 }, 1913 { 1914 title: compile("INFO: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected"), 1915 report: compile("INFO: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected \\](?:.*\\n)+?.*is trying to acquire(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"), 1916 fmt: "possible deadlock in %[1]v", 1917 reportType: crash.LockdepBug, 1918 }, 1919 { 1920 title: compile("INFO: possible recursive locking detected"), 1921 report: compile("INFO: possible recursive locking detected \\](?:.*\\n)+?.*is trying to acquire lock(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"), 1922 fmt: "possible deadlock in %[1]v", 1923 reportType: crash.LockdepBug, 1924 }, 1925 { 1926 title: compile("INFO: inconsistent lock state"), 1927 report: compile("INFO: inconsistent lock state \\](?:.*\\n)+?.*takes(?:.*\\n)+?.*at: {{PC}} +{{FUNC}}"), 1928 fmt: "inconsistent lock state in %[1]v", 1929 reportType: crash.LockdepBug, 1930 }, 1931 { 1932 title: compile("INFO: rcu_(?:preempt|sched|bh) (?:self-)?detected(?: expedited)? stall"), 1933 fmt: "INFO: rcu detected stall in %[1]v", 1934 alt: []string{"stall in %[1]v"}, 1935 stack: &stackFmt{ 1936 parts: []*regexp.Regexp{ 1937 compile("apic_timer_interrupt"), 1938 linuxRipFrame, 1939 parseStackTrace, 1940 }, 1941 parts2: []*regexp.Regexp{ 1942 compile("(?:apic_timer_interrupt|Exception stack|el1h_64_irq)"), 1943 parseStackTrace, 1944 }, 1945 skip: []string{"apic_timer_interrupt", "rcu"}, 1946 extractor: linuxStallFrameExtractor, 1947 }, 1948 reportType: crash.Hang, 1949 }, 1950 { 1951 title: compile("INFO: trying to register non-static key"), 1952 fmt: "INFO: trying to register non-static key in %[1]v", 1953 stack: &stackFmt{ 1954 parts: []*regexp.Regexp{ 1955 linuxCallTrace, 1956 parseStackTrace, 1957 }, 1958 skip: []string{"stack", "lock", "IRQ"}, 1959 }, 1960 }, 1961 { 1962 title: compile("INFO: suspicious RCU usage"), 1963 report: compile("INFO: suspicious RCU usage(?:.*\n)+?.*?{{SRC}}"), 1964 fmt: "INFO: suspicious RCU usage in %[2]v", 1965 stack: &stackFmt{ 1966 parts: []*regexp.Regexp{ 1967 linuxCallTrace, 1968 parseStackTrace, 1969 }, 1970 skip: []string{"rcu", "kmem", "slab"}, 1971 }, 1972 }, 1973 { 1974 title: compile("INFO: task .* blocked for more than [0-9]+ seconds"), 1975 fmt: "INFO: task hung in %[1]v", 1976 alt: []string{"hang in %[1]v"}, 1977 stack: &stackFmt{ 1978 parts: []*regexp.Regexp{ 1979 linuxCallTrace, 1980 parseStackTrace, 1981 }, 1982 extractor: linuxHangTaskFrameExtractor, 1983 }, 1984 reportType: crash.Hang, 1985 }, 1986 { 1987 title: compile("INFO: task .* can't die for more than .* seconds"), 1988 fmt: "INFO: task can't die in %[1]v", 1989 alt: []string{"hang in %[1]v"}, 1990 stack: &stackFmt{ 1991 parts: []*regexp.Regexp{ 1992 linuxCallTrace, 1993 parseStackTrace, 1994 }, 1995 skip: []string{"schedule"}, 1996 }, 1997 reportType: crash.Hang, 1998 }, 1999 { 2000 // This gets captured for corrupted old-style KASAN reports. 2001 title: compile("INFO: (Freed|Allocated) in (.*)"), 2002 fmt: "INFO: %[1]v in %[2]v", 2003 corrupted: true, 2004 }, 2005 { 2006 title: compile(`INFO:[[:space:]]*(?:\n|$)`), 2007 fmt: "INFO: corrupted", 2008 corrupted: true, 2009 }, 2010 }, 2011 []*regexp.Regexp{ 2012 compile("INFO: lockdep is turned off"), 2013 compile("INFO: Stall ended before state dump start"), 2014 compile("INFO: NMI handler"), 2015 compile("INFO: recovery required on readonly filesystem"), 2016 compile("(handler|interrupt).*took too long"), 2017 compile("_INFO::"), // Android can print this during boot. 2018 compile("INFO: sys_.* is not present in /proc/kallsyms"), // pkg/host output in debug mode 2019 compile("INFO: no syscalls can create resource"), // pkg/host output in debug mode 2020 compile("CAM_INFO:"), // Android prints this. 2021 compile("rmt_storage:INFO:"), // Android prints this. 2022 }, 2023 crash.UnknownType, 2024 }, 2025 { 2026 []byte("Unable to handle kernel"), 2027 []oopsFormat{ 2028 { 2029 title: compile("Unable to handle kernel (paging request|NULL pointer dereference|access to user memory)"), 2030 fmt: "BUG: unable to handle kernel %[1]v in %[2]v", 2031 alt: []string{"bad-access in %[2]v"}, 2032 stack: &stackFmt{ 2033 parts: []*regexp.Regexp{ 2034 linuxRipFrame, 2035 linuxCallTrace, 2036 parseStackTrace, 2037 }, 2038 }, 2039 }, 2040 }, 2041 []*regexp.Regexp{}, 2042 crash.UnknownType, 2043 }, 2044 { 2045 []byte("general protection fault"), 2046 []oopsFormat{ 2047 { 2048 title: compile("general protection fault.*:"), 2049 fmt: "general protection fault in %[1]v", 2050 alt: []string{"bad-access in %[1]v"}, 2051 stack: &stackFmt{ 2052 parts: []*regexp.Regexp{ 2053 linuxRipFrame, 2054 linuxCallTrace, 2055 parseStackTrace, 2056 }, 2057 }, 2058 }, 2059 }, 2060 []*regexp.Regexp{ 2061 compile(`general protection fault .* error:\d+ in `), 2062 }, 2063 crash.UnknownType, 2064 }, 2065 { 2066 []byte("stack segment: "), 2067 []oopsFormat{ 2068 { 2069 title: compile("stack segment: "), 2070 fmt: "stack segment fault in %[1]v", 2071 stack: &stackFmt{ 2072 parts: []*regexp.Regexp{ 2073 linuxRipFrame, 2074 linuxCallTrace, 2075 parseStackTrace, 2076 }, 2077 }, 2078 }, 2079 }, 2080 []*regexp.Regexp{}, 2081 crash.UnknownType, 2082 }, 2083 { 2084 []byte("Kernel panic"), 2085 []oopsFormat{ 2086 // Note: for stack corruption reports kernel may fail 2087 // to print function symbol name and/or unwind stack. 2088 { 2089 title: compile("Kernel panic - not syncing: stack-protector:"), 2090 report: compile("Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: {{FUNC}}"), 2091 fmt: "kernel panic: stack is corrupted in %[1]v", 2092 noStackTrace: true, 2093 }, 2094 { 2095 title: compile("Kernel panic - not syncing: stack-protector:"), 2096 report: compile("Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: [a-f0-9]+"), 2097 fmt: "kernel panic: stack is corrupted in %[1]v", 2098 stack: &stackFmt{ 2099 parts: []*regexp.Regexp{ 2100 linuxCallTrace, 2101 parseStackTrace, 2102 }, 2103 skip: []string{"stack_chk"}, 2104 }, 2105 }, 2106 { 2107 title: compile("Kernel panic - not syncing: corrupted stack end"), 2108 report: compile("Kernel panic - not syncing: corrupted stack end detected inside scheduler"), 2109 fmt: "kernel panic: corrupted stack end in %[1]v", 2110 alt: []string{"stack-overflow in %[1]v"}, 2111 stack: &stackFmt{ 2112 parts: []*regexp.Regexp{ 2113 linuxCallTrace, 2114 parseStackTrace, 2115 }, 2116 skip: []string{"schedule", "retint_kernel"}, 2117 extractor: linuxStallFrameExtractor, 2118 }, 2119 }, 2120 { 2121 title: compile("Kernel panic - not syncing: kernel stack overflow"), 2122 fmt: "kernel stack overflow in %[1]v", 2123 alt: []string{"stack-overflow in %[1]v"}, 2124 stack: &stackFmt{ 2125 parts: []*regexp.Regexp{ 2126 linuxCallTrace, 2127 parseStackTrace, 2128 }, 2129 skip: []string{"bad_stack"}, 2130 extractor: linuxStallFrameExtractor, 2131 }, 2132 }, 2133 { 2134 title: compile("Kernel panic - not syncing: Attempted to kill init!"), 2135 fmt: "kernel panic: Attempted to kill init!", 2136 }, 2137 { 2138 title: compile("Kernel panic - not syncing: Couldn't open N_TTY ldisc for [^ ]+ --- error -[0-9]+"), 2139 fmt: "kernel panic: Couldn't open N_TTY ldisc", 2140 }, 2141 { 2142 // 'kernel panic: Fatal exception' is usually printed after BUG, 2143 // so if we captured it as a report description, that means the 2144 // report got truncated and we missed the actual BUG header. 2145 title: compile("Kernel panic - not syncing: Fatal exception"), 2146 fmt: "kernel panic: Fatal exception", 2147 corrupted: true, 2148 }, 2149 { 2150 // Same, but for WARNINGs and KASAN reports. 2151 title: compile("Kernel panic - not syncing: panic_on_warn set"), 2152 fmt: "kernel panic: panic_on_warn set", 2153 corrupted: true, 2154 }, 2155 { 2156 // Same, but for task hung reports. 2157 title: compile("Kernel panic - not syncing: hung_task: blocked tasks"), 2158 fmt: "kernel panic: hung_task: blocked tasks", 2159 corrupted: true, 2160 }, 2161 { 2162 title: compile("Kernel panic - not syncing: (.*)"), 2163 fmt: "kernel panic: %[1]v", 2164 }, 2165 }, 2166 []*regexp.Regexp{}, 2167 crash.UnknownType, 2168 }, 2169 { 2170 []byte("PANIC: double fault"), 2171 []oopsFormat{ 2172 { 2173 title: compile("PANIC: double fault"), 2174 fmt: "PANIC: double fault in %[1]v", 2175 stack: &stackFmt{ 2176 parts: []*regexp.Regexp{ 2177 linuxRipFrame, 2178 }, 2179 }, 2180 }, 2181 }, 2182 []*regexp.Regexp{}, 2183 crash.UnknownType, 2184 }, 2185 { 2186 []byte("kernel BUG"), 2187 []oopsFormat{ 2188 { 2189 title: compile("kernel BUG at mm/usercopy.c"), 2190 fmt: "BUG: bad usercopy in %[1]v", 2191 stack: &stackFmt{ 2192 parts: []*regexp.Regexp{ 2193 linuxCallTrace, 2194 parseStackTrace, 2195 }, 2196 skip: []string{"usercopy", "__check"}, 2197 }, 2198 }, 2199 { 2200 title: compile("kernel BUG at lib/list_debug.c"), 2201 fmt: "BUG: corrupted list in %[1]v", 2202 alt: []string{"bad-access in %[1]v"}, // also sometimes due to memory corruption/race 2203 stack: &stackFmt{ 2204 parts: []*regexp.Regexp{ 2205 linuxCallTrace, 2206 parseStackTrace, 2207 }, 2208 }, 2209 }, 2210 { 2211 title: compile("kernel BUG at (.*)"), 2212 fmt: "kernel BUG in %[2]v", 2213 stack: &stackFmt{ 2214 parts: []*regexp.Regexp{ 2215 linuxRipFrame, 2216 linuxCallTrace, 2217 parseStackTrace, 2218 }, 2219 // Lots of skb wrappers contain BUG_ON, but the bug is almost always in the caller. 2220 skip: []string{"^skb_"}, 2221 }, 2222 }, 2223 }, 2224 []*regexp.Regexp{}, 2225 crash.Bug, 2226 }, 2227 { 2228 []byte("Kernel BUG"), 2229 []oopsFormat{ 2230 { 2231 title: compile("Kernel BUG (.*)"), 2232 fmt: "kernel BUG %[1]v", 2233 }, 2234 }, 2235 []*regexp.Regexp{}, 2236 crash.Bug, 2237 }, 2238 { 2239 []byte("BUG kmalloc-"), 2240 []oopsFormat{ 2241 { 2242 title: compile("BUG kmalloc-.*: Object already free"), 2243 fmt: "BUG: Object already free", 2244 }, 2245 }, 2246 []*regexp.Regexp{}, 2247 crash.UnknownType, 2248 }, 2249 { 2250 []byte("divide error:"), 2251 []oopsFormat{ 2252 { 2253 title: compile("divide error: "), 2254 fmt: "divide error in %[1]v", 2255 stack: &stackFmt{ 2256 parts: []*regexp.Regexp{ 2257 linuxRipFrame, 2258 }, 2259 }, 2260 }, 2261 }, 2262 []*regexp.Regexp{}, 2263 crash.UnknownType, 2264 }, 2265 { 2266 // A misspelling of the above introduced in 9d06c4027f21 ("x86/entry: Convert Divide Error to IDTENTRY"). 2267 []byte("divide_error:"), 2268 []oopsFormat{ 2269 { 2270 title: compile("divide_error: "), 2271 fmt: "divide error in %[1]v", 2272 stack: &stackFmt{ 2273 parts: []*regexp.Regexp{ 2274 linuxRipFrame, 2275 }, 2276 }, 2277 }, 2278 }, 2279 []*regexp.Regexp{}, 2280 crash.UnknownType, 2281 }, 2282 { 2283 []byte("invalid opcode:"), 2284 []oopsFormat{ 2285 { 2286 title: compile("invalid opcode: "), 2287 fmt: "invalid opcode in %[1]v", 2288 stack: &stackFmt{ 2289 parts: []*regexp.Regexp{ 2290 linuxRipFrame, 2291 }, 2292 }, 2293 }, 2294 }, 2295 []*regexp.Regexp{}, 2296 crash.UnknownType, 2297 }, 2298 { 2299 []byte("UBSAN:"), 2300 []oopsFormat{ 2301 { 2302 title: compile("UBSAN:"), 2303 report: compile("UBSAN: Undefined behaviour in"), 2304 fmt: "UBSAN: undefined-behaviour in %[1]v", 2305 stack: &stackFmt{ 2306 parts: []*regexp.Regexp{ 2307 linuxCallTrace, 2308 parseStackTrace, 2309 }, 2310 skip: []string{"ubsan", "overflow"}, 2311 }, 2312 }, 2313 { 2314 title: compile("UBSAN: array-index-out-of-bounds in"), 2315 fmt: "UBSAN: array-index-out-of-bounds in %[1]v", 2316 alt: []string{"bad-access in %[1]v"}, 2317 stack: &stackFmt{ 2318 parts: []*regexp.Regexp{ 2319 linuxCallTrace, 2320 parseStackTrace, 2321 }, 2322 skip: []string{"ubsan", "overflow"}, 2323 }, 2324 }, 2325 { 2326 title: compile("UBSAN:"), 2327 report: compile("UBSAN: (.*?) in"), 2328 fmt: "UBSAN: %[1]v in %[2]v", 2329 stack: &stackFmt{ 2330 parts: []*regexp.Regexp{ 2331 linuxCallTrace, 2332 parseStackTrace, 2333 }, 2334 skip: []string{"ubsan", "overflow"}, 2335 }, 2336 }, 2337 }, 2338 []*regexp.Regexp{}, 2339 crash.UBSAN, 2340 }, 2341 { 2342 []byte("Booting the kernel."), 2343 []oopsFormat{ 2344 { 2345 title: compile("Booting the kernel."), 2346 fmt: "unexpected kernel reboot", 2347 noStackTrace: true, 2348 reportType: crash.UnexpectedReboot, 2349 }, 2350 }, 2351 []*regexp.Regexp{ 2352 // These may appear on the same line when the fuzzer reads from the console the existing 2353 // boot message and then pass it as mount option, kernel then prints it back 2354 // as an invalid mount option and we detect false reboot. 2355 compile("Parsing ELF|Decompressing Linux"), 2356 }, 2357 crash.UnknownType, 2358 }, 2359 { 2360 []byte("unregister_netdevice: waiting for"), 2361 []oopsFormat{ 2362 { 2363 title: compile("unregister_netdevice: waiting for (?:.*) to become free"), 2364 fmt: "unregister_netdevice: waiting for DEV to become free", 2365 noStackTrace: true, 2366 }, 2367 }, 2368 []*regexp.Regexp{}, 2369 crash.UnknownType, 2370 }, 2371 { 2372 // Custom vfs error printed by older versions of the kernel, see #3621. 2373 []byte("VFS: Close: file count is 0"), 2374 []oopsFormat{ 2375 { 2376 title: compile("VFS: Close: file count is 0"), 2377 fmt: "VFS: Close: file count is zero (use-after-free)", 2378 noStackTrace: true, 2379 }, 2380 }, 2381 []*regexp.Regexp{}, 2382 crash.UnknownType, 2383 }, 2384 { 2385 // Custom vfs error printed by older versions of the kernel, see #3621. 2386 []byte("VFS: Busy inodes after unmount"), 2387 []oopsFormat{ 2388 { 2389 title: compile("VFS: Busy inodes after unmount"), 2390 fmt: "VFS: Busy inodes after unmount (use-after-free)", 2391 noStackTrace: true, 2392 }, 2393 }, 2394 []*regexp.Regexp{}, 2395 crash.UnknownType, 2396 }, 2397 { 2398 []byte("Internal error:"), 2399 []oopsFormat{ 2400 { 2401 title: compile("Internal error:"), 2402 fmt: "Internal error in %[1]v", 2403 // arm64 shows some crashes as "Internal error: synchronous external abort", 2404 // while arm shows the same crash as "Unable to handle kernel paging request", 2405 // so we need to merge them. 2406 alt: []string{"bad-access in %[1]v"}, 2407 stack: &stackFmt{ 2408 parts: []*regexp.Regexp{ 2409 linuxRipFrame, 2410 linuxCallTrace, 2411 parseStackTrace, 2412 }, 2413 }, 2414 }, 2415 }, 2416 []*regexp.Regexp{}, 2417 crash.UnknownType, 2418 }, 2419 { 2420 []byte("Unhandled fault:"), 2421 []oopsFormat{ 2422 { 2423 title: compile("Unhandled fault:"), 2424 fmt: "Unhandled fault in %[1]v", 2425 // x86_64 shows NULL derefs as "general protection fault", 2426 // while arm shows the same crash as "Unhandled fault: page domain fault". 2427 alt: []string{"bad-access in %[1]v"}, 2428 stack: &stackFmt{ 2429 parts: []*regexp.Regexp{ 2430 linuxRipFrame, 2431 linuxCallTrace, 2432 parseStackTrace, 2433 }, 2434 }, 2435 }, 2436 }, 2437 []*regexp.Regexp{}, 2438 crash.UnknownType, 2439 }, 2440 { 2441 []byte("Alignment trap:"), 2442 []oopsFormat{ 2443 { 2444 title: compile("Alignment trap:"), 2445 fmt: "Alignment trap in %[1]v", 2446 stack: &stackFmt{ 2447 parts: []*regexp.Regexp{ 2448 linuxRipFrame, 2449 linuxCallTrace, 2450 parseStackTrace, 2451 }, 2452 }, 2453 }, 2454 }, 2455 []*regexp.Regexp{}, 2456 crash.UnknownType, 2457 }, 2458 { 2459 []byte("trusty: panic"), 2460 []oopsFormat{ 2461 { 2462 title: compile("trusty: panic.* ASSERT FAILED"), 2463 report: compile("trusty: panic \\(.*?\\):(?: DEBUG)? ASSERT FAILED at \\(.*?\\): (.+)"), 2464 fmt: "trusty: ASSERT FAILED: %[1]v", 2465 noStackTrace: true, 2466 }, 2467 { 2468 title: compile("trusty: panic.* ASSERT FAILED.*: *(.*)"), 2469 fmt: "trusty: ASSERT FAILED: %[1]v", 2470 corrupted: true, 2471 }, 2472 { 2473 title: compile("trusty: panic"), 2474 report: compile("trusty: panic \\(.*?\\): (.+)"), 2475 fmt: "trusty: panic: %[1]v", 2476 noStackTrace: true, 2477 }, 2478 }, 2479 []*regexp.Regexp{}, 2480 crash.UnknownType, 2481 }, 2482 &groupGoRuntimeErrors, 2483 }, commonOopses...)