aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/vcs/linux_configs.go54
-rw-r--r--pkg/vcs/linux_configs_test.go93
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)
+}