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...)