From a0c7169a00e97fc53358f90c9d9c6f8fffddf904 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 28 Oct 2020 21:32:41 +0100 Subject: pkg/kconfig: accept target when parsing Kconfig Kconfig depends on the target arch. Add target argument for Kconfig parsing. Resolve $(SRCARCH) properly (previously we always assumed x86_64). --- pkg/bisect/bisect.go | 9 ++++++++- pkg/kconfig/fuzz.go | 6 +++++- pkg/kconfig/kconfig.go | 12 ++++++++---- pkg/kconfig/kconfig_test.go | 5 ++++- pkg/kconfig/minimize_test.go | 4 +++- pkg/vcs/linux.go | 5 +++-- pkg/vcs/testos.go | 4 +++- pkg/vcs/vcs.go | 3 ++- tools/syz-kconf/kconf.go | 8 +++----- tools/syz-minconfig/minconfig.go | 5 ++++- 10 files changed, 43 insertions(+), 18 deletions(-) diff --git a/pkg/bisect/bisect.go b/pkg/bisect/bisect.go index 9360bbab1..129a6686e 100644 --- a/pkg/bisect/bisect.go +++ b/pkg/bisect/bisect.go @@ -16,6 +16,7 @@ import ( "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/report" "github.com/google/syzkaller/pkg/vcs" + "github.com/google/syzkaller/sys/targets" ) type Config struct { @@ -62,6 +63,7 @@ type ReproConfig struct { type env struct { cfg *Config + target *targets.Target repo vcs.Repo bisecter vcs.Bisecter minimizer vcs.ConfigMinimizer @@ -132,8 +134,13 @@ func runImpl(cfg *Config, repo vcs.Repo, inst instance.Env) (*Result, error) { if !ok && len(cfg.Kernel.BaselineConfig) != 0 { return nil, fmt.Errorf("config minimization is not implemented for %v", cfg.Manager.TargetOS) } + target := targets.Get(cfg.Manager.TargetOS, cfg.Manager.TargetVMArch) + if target == nil { + return nil, fmt.Errorf("unknown target %v/%v", cfg.Manager.TargetOS, cfg.Manager.TargetVMArch) + } env := &env{ cfg: cfg, + target: target, repo: repo, bisecter: bisecter, minimizer: minimizer, @@ -298,7 +305,7 @@ func (env *env) minimizeConfig() (*testResult, error) { testResults[hash.Hash(test)] = testRes return testRes.verdict, err } - minConfig, err := env.minimizer.Minimize(env.cfg.Kernel.Config, + minConfig, err := env.minimizer.Minimize(env.target, env.cfg.Kernel.Config, env.cfg.Kernel.BaselineConfig, env.cfg.Trace, predMinimize) if err != nil { return nil, err diff --git a/pkg/kconfig/fuzz.go b/pkg/kconfig/fuzz.go index 953e750a5..554ad8afd 100644 --- a/pkg/kconfig/fuzz.go +++ b/pkg/kconfig/fuzz.go @@ -3,8 +3,12 @@ package kconfig +import ( + "github.com/google/syzkaller/sys/targets" +) + func FuzzParseKConfig(data []byte) int { - ParseData(data, "kconfig") + ParseData(targets.Get("linux", "amd64"), data, "kconfig") return 0 } diff --git a/pkg/kconfig/kconfig.go b/pkg/kconfig/kconfig.go index a4786711e..40e19b9af 100644 --- a/pkg/kconfig/kconfig.go +++ b/pkg/kconfig/kconfig.go @@ -12,6 +12,8 @@ import ( "path/filepath" "strings" "sync" + + "github.com/google/syzkaller/sys/targets" ) // KConfig represents a parsed Kconfig file (including includes). @@ -107,6 +109,7 @@ func (m *Menu) Prompt() string { type kconfigParser struct { *parser + target *targets.Target includes []*parser stack []*Menu cur *Menu @@ -114,17 +117,18 @@ type kconfigParser struct { helpIdent int } -func Parse(file string) (*KConfig, error) { +func Parse(target *targets.Target, file string) (*KConfig, error) { data, err := ioutil.ReadFile(file) if err != nil { return nil, fmt.Errorf("failed to open Kconfig file %v: %v", file, err) } - return ParseData(data, file) + return ParseData(target, data, file) } -func ParseData(data []byte, file string) (*KConfig, error) { +func ParseData(target *targets.Target, data []byte, file string) (*KConfig, error) { kp := &kconfigParser{ parser: newParser(data, file), + target: target, baseDir: filepath.Dir(file), } kp.parseFile() @@ -403,5 +407,5 @@ func (kp *kconfigParser) parseDefaultValue() { } func (kp *kconfigParser) expandString(str string) string { - return strings.Replace(str, "$(SRCARCH)", "x86", -1) + return strings.Replace(str, "$(SRCARCH)", kp.target.KernelHeaderArch, -1) } diff --git a/pkg/kconfig/kconfig_test.go b/pkg/kconfig/kconfig_test.go index e3bdd8668..994f1856f 100644 --- a/pkg/kconfig/kconfig_test.go +++ b/pkg/kconfig/kconfig_test.go @@ -6,6 +6,8 @@ package kconfig import ( "fmt" "testing" + + "github.com/google/syzkaller/sys/targets" ) func TestParseKConfig(t *testing.T) { @@ -21,9 +23,10 @@ config FOO `, }, } + target := targets.Get("linux", "amd64") for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { - kconf, err := ParseData([]byte(test.in), "Kconfig") + kconf, err := ParseData(target, []byte(test.in), "Kconfig") if err != nil { t.Fatal(err) } diff --git a/pkg/kconfig/minimize_test.go b/pkg/kconfig/minimize_test.go index 877df89b5..24738ebeb 100644 --- a/pkg/kconfig/minimize_test.go +++ b/pkg/kconfig/minimize_test.go @@ -7,6 +7,8 @@ import ( "bytes" "fmt" "testing" + + "github.com/google/syzkaller/sys/targets" ) func TestMinimize(t *testing.T) { @@ -62,7 +64,7 @@ CONFIG_C=y `, }, } - kconf, err := ParseData([]byte(kconfig), "kconf") + kconf, err := ParseData(targets.Get("linux", "amd64"), []byte(kconfig), "kconf") if err != nil { t.Fatal(err) } diff --git a/pkg/vcs/linux.go b/pkg/vcs/linux.go index 93a6ca910..a99215528 100644 --- a/pkg/vcs/linux.go +++ b/pkg/vcs/linux.go @@ -18,6 +18,7 @@ import ( "github.com/google/syzkaller/pkg/kconfig" "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/sys/targets" ) type linux struct { @@ -308,13 +309,13 @@ func ParseMaintainersLinux(text []byte) Recipients { const configBisectTag = "# Minimized by syzkaller" -func (ctx *linux) Minimize(original, baseline []byte, trace io.Writer, +func (ctx *linux) Minimize(target *targets.Target, original, baseline []byte, trace io.Writer, pred func(test []byte) (BisectResult, error)) ([]byte, error) { if bytes.HasPrefix(original, []byte(configBisectTag)) { fmt.Fprintf(trace, "# configuration already minimized\n") return original, nil } - kconf, err := kconfig.Parse(filepath.Join(ctx.git.dir, "Kconfig")) + kconf, err := kconfig.Parse(target, filepath.Join(ctx.git.dir, "Kconfig")) if err != nil { return nil, fmt.Errorf("failed to parse Kconfig: %v", err) } diff --git a/pkg/vcs/testos.go b/pkg/vcs/testos.go index 732192398..fa9f7cc9b 100644 --- a/pkg/vcs/testos.go +++ b/pkg/vcs/testos.go @@ -6,6 +6,8 @@ package vcs import ( "fmt" "io" + + "github.com/google/syzkaller/sys/targets" ) type testos struct { @@ -28,7 +30,7 @@ func (ctx *testos) EnvForCommit(binDir, commit string, kernelConfig []byte) (*Bi return &BisectEnv{KernelConfig: kernelConfig}, nil } -func (ctx *testos) Minimize(original, baseline []byte, trace io.Writer, +func (ctx *testos) Minimize(target *targets.Target, original, baseline []byte, trace io.Writer, pred func(test []byte) (BisectResult, error)) ([]byte, error) { if res, err := pred(baseline); err != nil { return nil, err diff --git a/pkg/vcs/vcs.go b/pkg/vcs/vcs.go index e79d1c18f..0f917144a 100644 --- a/pkg/vcs/vcs.go +++ b/pkg/vcs/vcs.go @@ -128,7 +128,8 @@ type Bisecter interface { } type ConfigMinimizer interface { - Minimize(original, baseline []byte, trace io.Writer, pred func(test []byte) (BisectResult, error)) ([]byte, error) + Minimize(target *targets.Target, original, baseline []byte, trace io.Writer, + pred func(test []byte) (BisectResult, error)) ([]byte, error) } type Commit struct { diff --git a/tools/syz-kconf/kconf.go b/tools/syz-kconf/kconf.go index 862e4ff45..e4a68998f 100644 --- a/tools/syz-kconf/kconf.go +++ b/tools/syz-kconf/kconf.go @@ -71,10 +71,6 @@ func main() { failf("failed to checkout %v/%v: %v", inst.Kernel.Repo, inst.Kernel.Tag, err) } } - kconf, err := kconfig.Parse(filepath.Join(*flagSourceDir, "Kconfig")) - if err != nil { - fail(err) - } releaseTag, err := repo.ReleaseTag("HEAD") if err != nil { fail(err) @@ -95,7 +91,6 @@ func main() { ConfigDir: filepath.Dir(*flagConfig), SourceDir: *flagSourceDir, ReleaseTag: releaseTag, - Kconf: kconf, } go func() { if err := ctx.generate(); err != nil { @@ -139,6 +134,9 @@ func (ctx *Context) generate() error { if err := ctx.setTarget(); err != nil { return err } + if ctx.Kconf, err = kconfig.Parse(ctx.Target, filepath.Join(ctx.SourceDir, "Kconfig")); err != nil { + return err + } if err := ctx.setReleaseFeatures(); err != nil { return err } diff --git a/tools/syz-minconfig/minconfig.go b/tools/syz-minconfig/minconfig.go index b68c183eb..91a26cdd1 100644 --- a/tools/syz-minconfig/minconfig.go +++ b/tools/syz-minconfig/minconfig.go @@ -13,9 +13,11 @@ import ( "fmt" "os" "path/filepath" + "runtime" "strings" "github.com/google/syzkaller/pkg/kconfig" + "github.com/google/syzkaller/sys/targets" ) func main() { @@ -24,9 +26,10 @@ func main() { flagBase = flag.String("base", "", "baseline config") flagFull = flag.String("full", "", "full config") flagConfigs = flag.String("configs", "", "comma-separated list of configs for the crash predicate") + flagArch = flag.String("arch", runtime.GOARCH, "kernel arch") ) flag.Parse() - kconf, err := kconfig.Parse(filepath.Join(*flagSourceDir, "Kconfig")) + kconf, err := kconfig.Parse(targets.Get("linux", *flagArch), filepath.Join(*flagSourceDir, "Kconfig")) if err != nil { failf("%v", err) } -- cgit mrf-deployment