github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/vcs/linux_configs.go (about)

     1  // Copyright 2023 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 vcs
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/google/syzkaller/pkg/debugtracer"
    10  	"github.com/google/syzkaller/pkg/kconfig"
    11  	"github.com/google/syzkaller/pkg/report/crash"
    12  )
    13  
    14  // setLinuxTagConfigs() disables Linux kernel configurations depending on the Linux kernel version,
    15  // which is determined by the git tags reachable from HEAD.
    16  // The problem is that Linux kernel is regularly broken w.r.t syzbot configs, especially on older versions.
    17  func setLinuxTagConfigs(cf *kconfig.ConfigFile, tags map[string]bool) {
    18  	const disableAlways = "disable-always"
    19  	// If tags is nil, disable only configs marked as disableAlways.
    20  	checkTag := func(tag string) bool {
    21  		return tags != nil && !tags[tag] ||
    22  			tags == nil && tag == disableAlways
    23  	}
    24  	disable := map[string]string{
    25  		// 5.2 has CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING which allows to test tomoyo better.
    26  		// This config also enables CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER
    27  		// but we need it disabled to boot older kernels.
    28  		"SECURITY_TOMOYO_OMIT_USERSPACE_LOADER": "v5.2",
    29  		// Kernel is boot broken before 4.15 due to double-free in vudc_probe:
    30  		// https://lkml.org/lkml/2018/9/7/648
    31  		// Fixed by e28fd56ad5273be67d0fae5bedc7e1680e729952.
    32  		"USBIP_VUDC": "v4.15",
    33  		// CONFIG_CAN causes:
    34  		// all runs: crashed: INFO: trying to register non-static key in can_notifier
    35  		// for v4.11..v4.12 and v4.12..v4.13 ranges.
    36  		// Fixed by 74b7b490886852582d986a33443c2ffa50970169.
    37  		"CAN": "v4.13",
    38  		// Setup of network devices is broken before v4.12 with a "WARNING in hsr_get_node".
    39  		// Fixed by 675c8da049fd6556eb2d6cdd745fe812752f07a8.
    40  		"HSR": "v4.12",
    41  		// Setup of network devices is broken before v4.12 with a "WARNING: ODEBUG bug in __sk_destruct"
    42  		// coming from smc_release.
    43  		"SMC": "v4.12",
    44  		// Kernel is boot broken before 4.10 with a lockdep warning in vhci_hcd_probe.
    45  		"USBIP_VHCI_HCD": "v4.10",
    46  		"BT_HCIVHCI":     "v4.10",
    47  		// Setup of network devices is broken before v4.7 with a deadlock involving team.
    48  		"NET_TEAM": "v4.7",
    49  		// Setup of network devices is broken before v4.5 with a warning in batadv_tvlv_container_remove.
    50  		"BATMAN_ADV": "v4.5",
    51  		// UBSAN is broken in multiple ways before v5.3, see:
    52  		// https://github.com/google/syzkaller/issues/1523#issuecomment-696514105
    53  		"UBSAN": "v5.3",
    54  		// First, we disable coverage in pkg/bisect because it fails machine testing starting from 4.7.
    55  		// Second, at 6689da155bdcd17abfe4d3a8b1e245d9ed4b5f2c CONFIG_KCOV selects CONFIG_GCC_PLUGIN_SANCOV
    56  		// (why?), which is build broken for hundreds of revisions.
    57  		// However, as there's a chance that KCOV might positively affect bug reproduction rate, let's
    58  		// keep it for newer kernel revisions. Bisection algorithm will try to drop it anyway during
    59  		// kernel config minimization.
    60  		"KCOV": "v5.4",
    61  		// This helps to produce stable binaries in presence of kernel tag changes.
    62  		"LOCALVERSION_AUTO": disableAlways,
    63  		// BTF fails lots of builds with:
    64  		// pahole version v1.9 is too old, need at least v1.13
    65  		// Failed to generate BTF for vmlinux. Try to disable CONFIG_DEBUG_INFO_BTF.
    66  		"DEBUG_INFO_BTF": disableAlways,
    67  		// This config only adds debug output. It should not be enabled at all,
    68  		// but it was accidentially enabled on some instances for some periods of time,
    69  		// and kernel is boot-broken for prolonged ranges of commits with deadlock
    70  		// which makes bisections take weeks.
    71  		"DEBUG_KOBJECT": disableAlways,
    72  		// This config is causing problems to kernel signature calculation as new initramfs is generated
    73  		// as a part of every build. Due to this init.data section containing this generated initramfs
    74  		// is differing between builds causing signture being random number.
    75  		"BLK_DEV_INITRD": disableAlways,
    76  	}
    77  	for cfg, tag := range disable {
    78  		if checkTag(tag) {
    79  			cf.Unset(cfg)
    80  		}
    81  	}
    82  	alter := []struct {
    83  		From string
    84  		To   string
    85  		Tag  string
    86  	}{
    87  		// Even though ORC unwinder was introduced a long time ago, it might have been broken for
    88  		// some time. 5.4 is chosen as a version tag, where ORC unwinder seems to work properly.
    89  		{"UNWINDER_ORC", "UNWINDER_FRAME_POINTER", "v5.4"},
    90  	}
    91  	for _, a := range alter {
    92  		if checkTag(a.Tag) {
    93  			cf.Unset(a.From)
    94  			cf.Set(a.To, kconfig.Yes)
    95  		}
    96  	}
    97  }
    98  
    99  // setLinuxSanitizerConfigs() removes Linux kernel sanitizers that are not necessary
   100  // to trigger the specified crash types.
   101  func setLinuxSanitizerConfigs(cf *kconfig.ConfigFile, types []crash.Type, dt debugtracer.DebugTracer) {
   102  	keep := map[crash.Type]func(){
   103  		crash.Hang: func() {
   104  			cf.Unset("RCU_STALL_COMMON")
   105  			cf.Unset("LOCKUP_DETECTOR")
   106  			cf.Unset("SOFTLOCKUP_DETECTOR")
   107  			cf.Unset("HARDLOCKUP_DETECTOR")
   108  			cf.Unset("DETECT_HUNG_TASK")
   109  			// It looks like it's the only reliable way to completely disable hung errors.
   110  			cmdline := cf.Value("CMDLINE")
   111  			pos := strings.LastIndexByte(cmdline, '"')
   112  			const rcuStallSuppress = "rcupdate.rcu_cpu_stall_suppress=1"
   113  			if pos >= 0 && !strings.Contains(cmdline, rcuStallSuppress) {
   114  				cf.Set("CMDLINE", cmdline[:pos]+" "+rcuStallSuppress+cmdline[pos:])
   115  			}
   116  		},
   117  		crash.MemoryLeak: func() { cf.Unset("DEBUG_KMEMLEAK") },
   118  		crash.UBSAN:      func() { cf.Unset("UBSAN") },
   119  		crash.Bug:        func() { cf.Unset("BUG") },
   120  		crash.KASAN:      func() { cf.Unset("KASAN") },
   121  		crash.LockdepBug: func() {
   122  			cf.Unset("LOCKDEP")
   123  			cf.Unset("PROVE_LOCKING") // it selects LOCKDEP
   124  		},
   125  		crash.AtomicSleep: func() { cf.Unset("DEBUG_ATOMIC_SLEEP") },
   126  	}
   127  	need := map[crash.Type]bool{}
   128  	for _, typ := range types {
   129  		if typ == crash.Warning {
   130  			// These are disabled together.
   131  			typ = crash.Bug
   132  		}
   133  		need[typ] = true
   134  	}
   135  	var disabled []string
   136  	for typ, f := range keep {
   137  		if need[typ] {
   138  			continue
   139  		}
   140  		f()
   141  		disabled = append(disabled, string(typ))
   142  	}
   143  	if len(disabled) > 0 {
   144  		dt.Log("disabling configs for %v, they are not needed", disabled)
   145  	}
   146  }