diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/vcs/linux_configs.go | 54 | ||||
| -rw-r--r-- | pkg/vcs/linux_configs_test.go | 93 |
2 files changed, 146 insertions, 1 deletions
diff --git a/pkg/vcs/linux_configs.go b/pkg/vcs/linux_configs.go index b54fed8fa..607a06285 100644 --- a/pkg/vcs/linux_configs.go +++ b/pkg/vcs/linux_configs.go @@ -3,7 +3,13 @@ package vcs -import "github.com/google/syzkaller/pkg/kconfig" +import ( + "strings" + + "github.com/google/syzkaller/pkg/debugtracer" + "github.com/google/syzkaller/pkg/kconfig" + "github.com/google/syzkaller/pkg/report/crash" +) // setLinuxTagConfigs() disables Linux kernel configurations depending on the Linux kernel version, // which is determined by the git tags reachable from HEAD. @@ -86,3 +92,49 @@ func setLinuxTagConfigs(cf *kconfig.ConfigFile, tags map[string]bool) { } } } + +// setLinuxSanitizerConfigs() removes Linux kernel sanitizers that are not necessary +// to trigger the specified crash types. +func setLinuxSanitizerConfigs(cf *kconfig.ConfigFile, types []crash.Type, dt debugtracer.DebugTracer) { + keep := map[crash.Type]func(){ + crash.Hang: func() { + cf.Unset("RCU_STALL_COMMON") + cf.Unset("LOCKUP_DETECTOR") + cf.Unset("SOFTLOCKUP_DETECTOR") + cf.Unset("HARDLOCKUP_DETECTOR") + cf.Unset("DETECT_HUNG_TASK") + // It looks like it's the only reliable way to completely disable hung errors. + val := cf.Value("CMDLINE") + pos := strings.LastIndexByte(val, '"') + if pos >= 0 { + cf.Set("CMDLINE", + val[:pos]+" rcupdate.rcu_cpu_stall_suppress=1"+val[pos:]) + } + }, + crash.MemoryLeak: func() { cf.Unset("DEBUG_KMEMLEAK") }, + crash.UBSAN: func() { cf.Unset("UBSAN") }, + crash.Bug: func() { cf.Unset("BUG") }, + crash.KASAN: func() { cf.Unset("KASAN") }, + crash.LockdepBug: func() { cf.Unset("LOCKDEP") }, + crash.AtomicSleep: func() { cf.Unset("DEBUG_ATOMIC_SLEEP") }, + } + need := map[crash.Type]bool{} + for _, typ := range types { + if typ == crash.Warning { + // These are disabled together. + typ = crash.Bug + } + need[typ] = true + } + var disabled []string + for typ, f := range keep { + if need[typ] { + continue + } + f() + disabled = append(disabled, string(typ)) + } + if len(disabled) > 0 { + dt.Log("disabling configs for %v, they are not needed", disabled) + } +} diff --git a/pkg/vcs/linux_configs_test.go b/pkg/vcs/linux_configs_test.go new file mode 100644 index 000000000..6ea95645f --- /dev/null +++ b/pkg/vcs/linux_configs_test.go @@ -0,0 +1,93 @@ +// Copyright 2023 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package vcs + +import ( + "testing" + + "github.com/google/syzkaller/pkg/debugtracer" + "github.com/google/syzkaller/pkg/kconfig" + "github.com/google/syzkaller/pkg/report/crash" + "github.com/stretchr/testify/assert" +) + +func TestDropLinuxSanitizerConfigs(t *testing.T) { + tests := []struct { + name string + types []crash.Type + test func(*testing.T, *kconfig.ConfigFile) + }{ + { + name: "warning", + types: []crash.Type{crash.Warning}, + test: func(t *testing.T, cf *kconfig.ConfigFile) { + assertConfigs(t, cf, "BUG") + assert.Equal(t, + `"param1=a param2=b rcupdate.rcu_cpu_stall_suppress=1"`, + cf.Value("CMDLINE"), + ) + }, + }, + { + name: "kasan bug", + types: []crash.Type{crash.KASAN}, + test: func(t *testing.T, cf *kconfig.ConfigFile) { + assertConfigs(t, cf, "KASAN") + }, + }, + { + name: "warning & kasan bug", + types: []crash.Type{crash.Warning, crash.KASAN}, + test: func(t *testing.T, cf *kconfig.ConfigFile) { + assertConfigs(t, cf, "KASAN", "BUG") + }, + }, + { + name: "lockdep", + types: []crash.Type{crash.LockdepBug}, + test: func(t *testing.T, cf *kconfig.ConfigFile) { + assertConfigs(t, cf, "LOCKDEP") + }, + }, + { + name: "rcu stall", + types: []crash.Type{crash.Hang}, + test: func(t *testing.T, cf *kconfig.ConfigFile) { + assertConfigs(t, cf, "RCU_STALL_COMMON") + assert.Equal(t, `"param1=a param2=b"`, cf.Value("CMDLINE")) + }, + }, + } + + const base = ` +CONFIG_CMDLINE="param1=a param2=b" +CONFIG_BUG=y +CONFIG_KASAN=y +CONFIG_LOCKDEP=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_UBSAN=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +` + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + conf, err := kconfig.ParseConfigData([]byte(base), "base") + if err != nil { + t.Fatal(err) + } + setLinuxSanitizerConfigs(conf, test.types, &debugtracer.NullTracer{}) + test.test(t, conf) + }) + } +} + +func assertConfigs(t *testing.T, cf *kconfig.ConfigFile, names ...string) { + var setConfigs []string + for _, name := range names { + if cf.Value(name) == kconfig.Yes { + setConfigs = append(setConfigs, name) + } + } + assert.ElementsMatch(t, setConfigs, names) +} |
