aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg/bisect/bisect.go25
-rw-r--r--pkg/vcs/linux.go80
-rw-r--r--pkg/vcs/testos.go4
-rw-r--r--pkg/vcs/vcs.go4
-rw-r--r--syz-ci/jobs.go9
-rw-r--r--syz-ci/syz-ci.go29
-rw-r--r--tools/syz-bisect/bisect.go13
-rw-r--r--tools/syz-testbuild/testbuild.go4
8 files changed, 107 insertions, 61 deletions
diff --git a/pkg/bisect/bisect.go b/pkg/bisect/bisect.go
index 0948bc653..1813abaa5 100644
--- a/pkg/bisect/bisect.go
+++ b/pkg/bisect/bisect.go
@@ -19,15 +19,16 @@ import (
)
type Config struct {
- Trace debugtracer.DebugTracer
- Fix bool
- BinDir string
- Ccache string
- Timeout time.Duration
- Kernel KernelConfig
- Syzkaller SyzkallerConfig
- Repro ReproConfig
- Manager *mgrconfig.Config
+ Trace debugtracer.DebugTracer
+ Fix bool
+ BisectCompiler string
+ BinDir string
+ Ccache string
+ Timeout time.Duration
+ Kernel KernelConfig
+ Syzkaller SyzkallerConfig
+ Repro ReproConfig
+ Manager *mgrconfig.Config
}
type KernelConfig struct {
@@ -375,7 +376,7 @@ func (env *env) commitRangeForFix() (*vcs.Commit, *vcs.Commit, *report.Report, [
func (env *env) commitRangeForBug() (*vcs.Commit, *vcs.Commit, *report.Report, []*testResult, error) {
cfg := env.cfg
- tags, err := env.bisecter.PreviousReleaseTags(cfg.Kernel.Commit)
+ tags, err := env.bisecter.PreviousReleaseTags(cfg.Kernel.Commit, cfg.BisectCompiler)
if err != nil {
return nil, nil, nil, nil, err
}
@@ -420,11 +421,11 @@ func (env *env) build() (*vcs.Commit, string, error) {
return nil, "", err
}
- bisectEnv, err := env.bisecter.EnvForCommit(env.cfg.BinDir, current.Hash, env.kernelConfig)
+ bisectEnv, err := env.bisecter.EnvForCommit(env.cfg.BisectCompiler, env.cfg.BinDir, current.Hash, env.kernelConfig)
if err != nil {
return current, "", err
}
- env.log("testing commit %v", current.Hash)
+ env.log("testing commit %v %v", current.Hash, env.cfg.BisectCompiler)
buildStart := time.Now()
mgr := env.cfg.Manager
if err := build.Clean(mgr.TargetOS, mgr.TargetVMArch, mgr.Type, mgr.KernelSrc); err != nil {
diff --git a/pkg/vcs/linux.go b/pkg/vcs/linux.go
index d2371ca5c..8ee801430 100644
--- a/pkg/vcs/linux.go
+++ b/pkg/vcs/linux.go
@@ -42,32 +42,43 @@ func newLinux(dir string, opts []RepoOpt, vmType string) *linux {
}
}
-func (ctx *linux) PreviousReleaseTags(commit string) ([]string, error) {
+func (ctx *linux) PreviousReleaseTags(commit, bisectCompiler string) ([]string, error) {
tags, err := ctx.git.previousReleaseTags(commit, false, false, false)
if err != nil {
return nil, err
}
+
+ cutoff := ""
+ if bisectCompiler == "gcc" {
+ // Initially we tried to stop at 3.8 because:
+ // v3.8 does not work with modern perl, and as we go further in history
+ // make stops to work, then binutils, glibc, etc. So we stop at v3.8.
+ // Up to that point we only need an ancient gcc.
+ //
+ // But kernels don't boot starting from 4.0 and back.
+ // That was fixed by 99124e4db5b7b70daeaaf1d88a6a8078a0004c6e,
+ // and it can be cherry-picked into 3.14..4.0 but it conflicts for 3.13 and older.
+ //
+ // But starting from 4.0 our user-space binaries start crashing with
+ // assorted errors which suggests process memory corruption by kernel.
+ //
+ // We used to use 4.1 as the oldest tested release (it works in general).
+ // However, there is correlation between how far back we go and probability
+ // of getting correct result (see #1532). So we now stop at 4.6.
+ // 4.6 is somewhat arbitrary, we've seen lots of wrong results in 4.5..4.6 range,
+ // but there is definitive reason for 4.6. Most likely later we want to bump it
+ // even more (as new releases are produced). Next good candidate may be 4.11
+ // because then we won't need gcc 5.5.
+ cutoff = "v4.5"
+ } else if bisectCompiler == "clang" {
+ // v5.3 was the first release with solid clang support, however I was able to
+ // compile v5.1..v5.3 using a newer defconfig + make oldconfig. Everything older
+ // would require further cherry-picks.
+ cutoff = "v5.2"
+ }
+
for i, tag := range tags {
- if tag == "v4.5" {
- // Initially we tried to stop at 3.8 because:
- // v3.8 does not work with modern perl, and as we go further in history
- // make stops to work, then binutils, glibc, etc. So we stop at v3.8.
- // Up to that point we only need an ancient gcc.
- //
- // But kernels don't boot starting from 4.0 and back.
- // That was fixed by 99124e4db5b7b70daeaaf1d88a6a8078a0004c6e,
- // and it can be cherry-picked into 3.14..4.0 but it conflicts for 3.13 and older.
- //
- // But starting from 4.0 our user-space binaries start crashing with
- // assorted errors which suggests process memory corruption by kernel.
- //
- // We used to use 4.1 as the oldest tested release (it works in general).
- // However, there is correlation between how far back we go and probability
- // of getting correct result (see #1532). So we now stop at 4.6.
- // 4.6 is somewhat arbitrary, we've seen lots of wrong results in 4.5..4.6 range,
- // but there is definitive reason for 4.6. Most likely later we want to bump it
- // even more (as new releases are produced). Next good candidate may be 4.11
- // because then we won't need gcc 5.5.
+ if tag == cutoff {
tags = tags[:i]
break
}
@@ -121,7 +132,7 @@ func gitReleaseTagToInt(tag string, includeRC bool) uint64 {
return v1*1e9 + v2*1e6 + rc*1e3 + v3
}
-func (ctx *linux) EnvForCommit(binDir, commit string, kernelConfig []byte) (*BisectEnv, error) {
+func (ctx *linux) EnvForCommit(bisectCompiler, binDir, commit string, kernelConfig []byte) (*BisectEnv, error) {
tagList, err := ctx.previousReleaseTags(commit, true, false, false)
if err != nil {
return nil, err
@@ -135,8 +146,18 @@ func (ctx *linux) EnvForCommit(binDir, commit string, kernelConfig []byte) (*Bis
return nil, err
}
linuxAlterConfigs(cf, tags)
+
+ compiler := ""
+ if bisectCompiler == "gcc" {
+ compiler = filepath.Join(binDir, "gcc-"+linuxGCCVersion(tags), "bin", "gcc")
+ } else if bisectCompiler == "clang" {
+ compiler = filepath.Join(binDir, "llvm-"+linuxClangVersion(tags), "bin", "clang")
+ } else {
+ return nil, fmt.Errorf("unsupported bisect compiler: %v", bisectCompiler)
+ }
+
env := &BisectEnv{
- Compiler: filepath.Join(binDir, "gcc-"+linuxCompilerVersion(tags), "bin", "gcc"),
+ Compiler: compiler,
KernelConfig: cf.Serialize(),
}
@@ -159,7 +180,18 @@ func (ctx *linux) EnvForCommit(binDir, commit string, kernelConfig []byte) (*Bis
return env, nil
}
-func linuxCompilerVersion(tags map[string]bool) string {
+func linuxClangVersion(tags map[string]bool) string {
+ switch {
+ case tags["v5.9"]:
+ return "14.0.6"
+ default:
+ // everything before v5.3 might not work great
+ // everything before v5.1 does not work
+ return "9.0.1"
+ }
+}
+
+func linuxGCCVersion(tags map[string]bool) string {
switch {
case tags["v5.9"]:
return "10.1.0"
diff --git a/pkg/vcs/testos.go b/pkg/vcs/testos.go
index baadb1a2a..0053a528e 100644
--- a/pkg/vcs/testos.go
+++ b/pkg/vcs/testos.go
@@ -22,11 +22,11 @@ func newTestos(dir string, opts []RepoOpt) *testos {
}
}
-func (ctx *testos) PreviousReleaseTags(commit string) ([]string, error) {
+func (ctx *testos) PreviousReleaseTags(commit, bisectCompiler string) ([]string, error) {
return ctx.git.previousReleaseTags(commit, false, false, false)
}
-func (ctx *testos) EnvForCommit(binDir, commit string, kernelConfig []byte) (*BisectEnv, error) {
+func (ctx *testos) EnvForCommit(bisectCompiler, binDir, commit string, kernelConfig []byte) (*BisectEnv, error) {
return &BisectEnv{KernelConfig: kernelConfig}, nil
}
diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go
index ae7bc8508..4e42b04a0 100644
--- a/pkg/vcs/vcs.go
+++ b/pkg/vcs/vcs.go
@@ -78,11 +78,11 @@ type Bisecter interface {
// PreviousReleaseTags returns list of preceding release tags that are reachable from the given commit.
// If the commit itself has a release tag, this tag is not included.
- PreviousReleaseTags(commit string) ([]string, error)
+ PreviousReleaseTags(commit, bisectCompiler string) ([]string, error)
IsRelease(commit string) (bool, error)
- EnvForCommit(binDir, commit string, kernelConfig []byte) (*BisectEnv, error)
+ EnvForCommit(bisectCompiler, binDir, commit string, kernelConfig []byte) (*BisectEnv, error)
}
type ConfigMinimizer interface {
diff --git a/syz-ci/jobs.go b/syz-ci/jobs.go
index c77cb3f26..5a4addb02 100644
--- a/syz-ci/jobs.go
+++ b/syz-ci/jobs.go
@@ -412,10 +412,11 @@ func (jp *JobProcessor) bisect(job *Job, mgrcfg *mgrconfig.Config) error {
// compete with patch testing jobs (it's bad delaying patch testing).
// When/if bisection jobs don't compete with patch testing,
// it makes sense to increase this to 12-24h.
- Timeout: 8 * time.Hour,
- Fix: req.Type == dashapi.JobBisectFix,
- BinDir: jp.cfg.BisectBinDir,
- Ccache: jp.cfg.Ccache,
+ Timeout: 8 * time.Hour,
+ Fix: req.Type == dashapi.JobBisectFix,
+ BisectCompiler: mgr.mgrcfg.BisectCompiler,
+ BinDir: jp.cfg.BisectBinDir,
+ Ccache: jp.cfg.Ccache,
Kernel: bisect.KernelConfig{
Repo: mgr.mgrcfg.Repo,
Branch: mgr.mgrcfg.Branch,
diff --git a/syz-ci/syz-ci.go b/syz-ci/syz-ci.go
index 54d9b877c..944c0c745 100644
--- a/syz-ci/syz-ci.go
+++ b/syz-ci/syz-ci.go
@@ -102,10 +102,13 @@ type Config struct {
CoverUploadPath string `json:"cover_upload_path"`
// Path to upload corpus.db from managers (optional).
// Supported protocols: GCS (gs://) and HTTP PUT (http:// or https://).
- CorpusUploadPath string `json:"corpus_upload_path"`
- BisectBinDir string `json:"bisect_bin_dir"`
- Ccache string `json:"ccache"`
- Managers []*ManagerConfig `json:"managers"`
+ CorpusUploadPath string `json:"corpus_upload_path"`
+ // BinDir must point to a dir that contains compilers required to build
+ // older versions of the kernel. For linux, it needs to include several
+ // compiler versions.
+ BisectBinDir string `json:"bisect_bin_dir"`
+ Ccache string `json:"ccache"`
+ Managers []*ManagerConfig `json:"managers"`
// Poll period for jobs in seconds (optional, defaults to 10 seconds)
JobPollPeriod int `json:"job_poll_period"`
// Poll period for commits in seconds (optional, defaults to 3600 seconds)
@@ -149,12 +152,15 @@ type ManagerConfig struct {
DashboardKey string `json:"dashboard_key"`
Repo string `json:"repo"`
// Short name of the repo (e.g. "linux-next"), used only for reporting.
- RepoAlias string `json:"repo_alias"`
- Branch string `json:"branch"` // Defaults to "master".
- Compiler string `json:"compiler"`
- Ccache string `json:"ccache"`
- Userspace string `json:"userspace"`
- KernelConfig string `json:"kernel_config"`
+ RepoAlias string `json:"repo_alias"`
+ // Currently either 'gcc' or 'clang'. Note that pkg/bisect requires
+ // explicit plumbing for every os/compiler combination.
+ BisectCompiler string `json:"bisect_compiler"` // Defaults to "gcc"
+ Branch string `json:"branch"` // Defaults to "master".
+ Compiler string `json:"compiler"`
+ Ccache string `json:"ccache"`
+ Userspace string `json:"userspace"`
+ KernelConfig string `json:"kernel_config"`
// Baseline config for bisection, see pkg/bisect.KernelConfig.BaselineConfig.
KernelBaselineConfig string `json:"kernel_baseline_config"`
// File with kernel cmdline values (optional).
@@ -380,6 +386,9 @@ func loadManagerConfig(cfg *Config, mgr *ManagerConfig) error {
if !managerNameRe.MatchString(mgr.Name) {
return fmt.Errorf("param 'managers.name' has bad value: %q", mgr.Name)
}
+ if mgr.BisectCompiler == "" {
+ mgr.BisectCompiler = "gcc"
+ }
if mgr.Branch == "" {
mgr.Branch = "master"
}
diff --git a/tools/syz-bisect/bisect.go b/tools/syz-bisect/bisect.go
index 1c8692700..9712ddcd3 100644
--- a/tools/syz-bisect/bisect.go
+++ b/tools/syz-bisect/bisect.go
@@ -43,10 +43,12 @@ var (
)
type Config struct {
+ // Currently either 'gcc' or 'clang'. Note that pkg/bisect requires
+ // explicit plumbing for every os/compiler combination.
+ BisectCompiler string `json:"bisect_compiler"`
// BinDir must point to a dir that contains compilers required to build
// older versions of the kernel. For linux, it needs to include several
- // gcc versions. A working archive can be downloaded from:
- // https://storage.googleapis.com/syzkaller/bisect_bin.tar.gz
+ // compiler versions.
BinDir string `json:"bin_dir"`
Ccache string `json:"ccache"`
KernelRepo string `json:"kernel_repo"`
@@ -94,9 +96,10 @@ func main() {
TraceWriter: os.Stdout,
OutDir: *flagCrash,
},
- Fix: *flagFix,
- BinDir: mycfg.BinDir,
- Ccache: mycfg.Ccache,
+ Fix: *flagFix,
+ BisectCompiler: mycfg.BisectCompiler,
+ BinDir: mycfg.BinDir,
+ Ccache: mycfg.Ccache,
Kernel: bisect.KernelConfig{
Repo: mycfg.KernelRepo,
Branch: mycfg.KernelBranch,
diff --git a/tools/syz-testbuild/testbuild.go b/tools/syz-testbuild/testbuild.go
index 9fe1dd3f1..be2718b3a 100644
--- a/tools/syz-testbuild/testbuild.go
+++ b/tools/syz-testbuild/testbuild.go
@@ -101,7 +101,7 @@ func main() {
tool.Fail(err)
}
log.Printf("HEAD is on %v %v", head.Hash, head.Title)
- tags, err := bisecter.PreviousReleaseTags(head.Hash)
+ tags, err := bisecter.PreviousReleaseTags(head.Hash, "gcc")
if err != nil {
tool.Fail(err)
}
@@ -125,7 +125,7 @@ func main() {
}
func test(repo vcs.Repo, bisecter vcs.Bisecter, kernelConfig []byte, env instance.Env, com *vcs.Commit) {
- bisectEnv, err := bisecter.EnvForCommit(*flagBisectBin, com.Hash, kernelConfig)
+ bisectEnv, err := bisecter.EnvForCommit("gcc", *flagBisectBin, com.Hash, kernelConfig)
if err != nil {
tool.Fail(err)
}