1// Copyright 2018 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
4package main
5
6import (
7	"encoding/json"
8	"flag"
9	"fmt"
10	"io/ioutil"
11	"os"
12	"path/filepath"
13	"strings"
14
15	"github.com/google/syzkaller/pkg/bisect"
16	"github.com/google/syzkaller/pkg/config"
17	"github.com/google/syzkaller/pkg/mgrconfig"
18)
19
20var (
21	flagConfig = flag.String("config", "", "bisect config file")
22	flagCrash  = flag.String("crash", "", "dir with crash info")
23	flagFix    = flag.Bool("fix", false, "search for crash fix")
24)
25
26type Config struct {
27	BinDir        string          `json:"bin_dir"`
28	KernelRepo    string          `json:"kernel_repo"`
29	KernelBranch  string          `json:"kernel_branch"`
30	Compiler      string          `json:"compiler"`
31	Userspace     string          `json:"userspace"`
32	Sysctl        string          `json:"sysctl"`
33	Cmdline       string          `json:"cmdline"`
34	SyzkallerRepo string          `json:"syzkaller_repo"`
35	Manager       json.RawMessage `json:"manager"`
36}
37
38func main() {
39	flag.Parse()
40	os.Setenv("SYZ_DISABLE_SANDBOXING", "yes")
41	mycfg := new(Config)
42	if err := config.LoadFile(*flagConfig, mycfg); err != nil {
43		fmt.Fprintln(os.Stderr, err)
44		os.Exit(1)
45	}
46	mgrcfg, err := mgrconfig.LoadPartialData(mycfg.Manager)
47	if err != nil {
48		fmt.Fprintln(os.Stderr, err)
49		os.Exit(1)
50	}
51	if mgrcfg.Workdir == "" {
52		mgrcfg.Workdir, err = ioutil.TempDir("", "syz-bisect")
53		if err != nil {
54			fmt.Fprintf(os.Stderr, "failed to create temp dir: %v\n", err)
55			os.Exit(1)
56		}
57		defer os.RemoveAll(mgrcfg.Workdir)
58	}
59	cfg := &bisect.Config{
60		Trace:    os.Stdout,
61		Fix:      *flagFix,
62		BinDir:   mycfg.BinDir,
63		DebugDir: *flagCrash,
64		Kernel: bisect.KernelConfig{
65			Repo:      mycfg.KernelRepo,
66			Branch:    mycfg.KernelBranch,
67			Userspace: mycfg.Userspace,
68			Sysctl:    mycfg.Sysctl,
69			Cmdline:   mycfg.Cmdline,
70		},
71		Syzkaller: bisect.SyzkallerConfig{
72			Repo: mycfg.SyzkallerRepo,
73		},
74		Manager: *mgrcfg,
75	}
76	loadString("syzkaller.commit", &cfg.Syzkaller.Commit)
77	loadString("kernel.commit", &cfg.Kernel.Commit)
78	loadFile("kernel.config", &cfg.Kernel.Config)
79	loadFile("repro.syz", &cfg.Repro.Syz)
80	loadFile("repro.opts", &cfg.Repro.Opts)
81	bisect.Run(cfg)
82}
83
84func loadString(file string, dst *string) {
85	data, err := ioutil.ReadFile(filepath.Join(*flagCrash, file))
86	if err != nil {
87		fmt.Fprintln(os.Stderr, err)
88		os.Exit(1)
89	}
90	*dst = strings.TrimSpace(string(data))
91}
92
93func loadFile(file string, dst *[]byte) {
94	data, err := ioutil.ReadFile(filepath.Join(*flagCrash, file))
95	if err != nil {
96		fmt.Fprintln(os.Stderr, err)
97		os.Exit(1)
98	}
99	*dst = data
100}
101