OLD | NEW |
1 package main | 1 package main |
2 | 2 |
3 /* | 3 /* |
4 Runs the backend portions of the fuzzer. This includes the generator and aggreg
ator parts (see DESIGN.md) | 4 Runs the backend portions of the fuzzer. This includes the generator and aggreg
ator parts (see DESIGN.md) |
5 */ | 5 */ |
6 | 6 |
7 import ( | 7 import ( |
8 "flag" | 8 "flag" |
9 "fmt" | 9 "fmt" |
10 "os" | 10 "os" |
11 "path/filepath" | 11 "path/filepath" |
12 "time" | 12 "time" |
13 | 13 |
14 "github.com/skia-dev/glog" | 14 "github.com/skia-dev/glog" |
15 "go.skia.org/infra/fuzzer/go/aggregator" | 15 "go.skia.org/infra/fuzzer/go/aggregator" |
16 "go.skia.org/infra/fuzzer/go/backend" | 16 "go.skia.org/infra/fuzzer/go/backend" |
17 fcommon "go.skia.org/infra/fuzzer/go/common" | 17 fcommon "go.skia.org/infra/fuzzer/go/common" |
18 "go.skia.org/infra/fuzzer/go/config" | 18 "go.skia.org/infra/fuzzer/go/config" |
19 "go.skia.org/infra/fuzzer/go/generator" | 19 "go.skia.org/infra/fuzzer/go/generator" |
20 "go.skia.org/infra/go/auth" | 20 "go.skia.org/infra/go/auth" |
21 "go.skia.org/infra/go/common" | 21 "go.skia.org/infra/go/common" |
22 "go.skia.org/infra/go/fileutil" | 22 "go.skia.org/infra/go/fileutil" |
| 23 "go.skia.org/infra/go/influxdb" |
23 "golang.org/x/net/context" | 24 "golang.org/x/net/context" |
24 "google.golang.org/cloud" | 25 "google.golang.org/cloud" |
25 "google.golang.org/cloud/storage" | 26 "google.golang.org/cloud/storage" |
26 ) | 27 ) |
27 | 28 |
28 var ( | 29 var ( |
29 aflOutputPath = flag.String("afl_output_path", "", "[REQUIRED] The
output folder of afl-fuzz. This will have on folder for each fuzz_to_run. Each
of those will have N folders named fuzzer0 - fuzzerN. Should not be in /tmp or
afl-fuzz will refuse to run.") | 30 aflOutputPath = flag.String("afl_output_path", "", "[REQUIRED] The
output folder of afl-fuzz. This will have on folder for each fuzz_to_run. Each
of those will have N folders named fuzzer0 - fuzzerN. Should not be in /tmp or
afl-fuzz will refuse to run.") |
30 generatorWD = flag.String("generator_working_dir", "", "[REQUIRED
] The generator's working directory. Should not be in /tmp.") | 31 generatorWD = flag.String("generator_working_dir", "", "[REQUIRED
] The generator's working directory. Should not be in /tmp.") |
31 fuzzSamples = flag.String("fuzz_samples", "", "[REQUIRED] The gen
erator's working directory. Should not be in /tmp.") | 32 fuzzSamples = flag.String("fuzz_samples", "", "[REQUIRED] The gen
erator's working directory. Should not be in /tmp.") |
32 skiaRoot = flag.String("skia_root", "", "[REQUIRED] The root d
irectory of the Skia source code.") | 33 skiaRoot = flag.String("skia_root", "", "[REQUIRED] The root d
irectory of the Skia source code.") |
33 clangPath = flag.String("clang_path", "", "[REQUIRED] The path
to the clang executable.") | 34 clangPath = flag.String("clang_path", "", "[REQUIRED] The path
to the clang executable.") |
34 clangPlusPlusPath = flag.String("clang_p_p_path", "", "[REQUIRED] The p
ath to the clang++ executable.") | 35 clangPlusPlusPath = flag.String("clang_p_p_path", "", "[REQUIRED] The p
ath to the clang++ executable.") |
35 depotToolsPath = flag.String("depot_tools_path", "", "The absolute p
ath to depot_tools. Can be empty if they are on your path.") | 36 depotToolsPath = flag.String("depot_tools_path", "", "The absolute p
ath to depot_tools. Can be empty if they are on your path.") |
36 aflRoot = flag.String("afl_root", "", "[REQUIRED] The install
directory of afl-fuzz (v1.94b or later).") | 37 aflRoot = flag.String("afl_root", "", "[REQUIRED] The install
directory of afl-fuzz (v1.94b or later).") |
37 numFuzzProcesses = flag.Int("fuzz_processes", 0, `The number of proces
ses to run afl-fuzz [per fuzz to run]. This should be fewer than the number of
logical cores. Defaults to 0, which means "Make an intelligent guess"`) | 38 numFuzzProcesses = flag.Int("fuzz_processes", 0, `The number of proces
ses to run afl-fuzz [per fuzz to run]. This should be fewer than the number of
logical cores. Defaults to 0, which means "Make an intelligent guess"`) |
38 versionCheckPeriod = flag.Duration("version_check_period", 20*time.Secon
d, `The period used to check the version of Skia that needs fuzzing.`) | 39 versionCheckPeriod = flag.Duration("version_check_period", 20*time.Secon
d, `The period used to check the version of Skia that needs fuzzing.`) |
39 downloadProcesses = flag.Int("download_processes", 4, "The number of do
wnload processes to be used for fetching fuzzes when re-analyzing them. This is
constant with respect to the number of fuzzes.") | 40 downloadProcesses = flag.Int("download_processes", 4, "The number of do
wnload processes to be used for fetching fuzzes when re-analyzing them. This is
constant with respect to the number of fuzzes.") |
40 fuzzesToRun = common.NewMultiStringFlag("fuzz_to_run", nil, fmt.S
printf("A set of fuzzes to run. Can be one or more of the known fuzzes: %q", fc
ommon.FUZZ_CATEGORIES)) | 41 fuzzesToRun = common.NewMultiStringFlag("fuzz_to_run", nil, fmt.S
printf("A set of fuzzes to run. Can be one or more of the known fuzzes: %q", fc
ommon.FUZZ_CATEGORIES)) |
41 | 42 |
42 bucket = flag.String("bucket", "skia-fuzzer", "The GCS buc
ket in which to store found fuzzes.") | 43 bucket = flag.String("bucket", "skia-fuzzer", "The GCS buc
ket in which to store found fuzzes.") |
43 fuzzPath = flag.String("fuzz_path", filepath.Join(os.TempDir
(), "fuzzes"), "The directory to temporarily store the binary fuzzes during aggr
egation.") | 44 fuzzPath = flag.String("fuzz_path", filepath.Join(os.TempDir
(), "fuzzes"), "The directory to temporarily store the binary fuzzes during aggr
egation.") |
44 executablePath = flag.String("executable_path", filepath.Join(os.T
empDir(), "executables"), "The directory to store temporary executables that wil
l run the fuzzes during aggregation. Defaults to /tmp/executables.") | 45 executablePath = flag.String("executable_path", filepath.Join(os.T
empDir(), "executables"), "The directory to store temporary executables that wil
l run the fuzzes during aggregation. Defaults to /tmp/executables.") |
45 numAnalysisProcesses = flag.Int("analysis_processes", 0, `The number of
processes to analyze fuzzes [per fuzz to run]. This should be fewer than the nu
mber of logical cores. Defaults to 0, which means "Make an intelligent guess"`) | 46 numAnalysisProcesses = flag.Int("analysis_processes", 0, `The number of
processes to analyze fuzzes [per fuzz to run]. This should be fewer than the nu
mber of logical cores. Defaults to 0, which means "Make an intelligent guess"`) |
46 rescanPeriod = flag.Duration("rescan_period", 60*time.Second, `T
he time in which to sleep for every cycle of aggregation. `) | 47 rescanPeriod = flag.Duration("rescan_period", 60*time.Second, `T
he time in which to sleep for every cycle of aggregation. `) |
47 numUploadProcesses = flag.Int("upload_processes", 0, `The number of pr
ocesses to upload fuzzes [per fuzz to run]. Defaults to 0, which means "Make an
intelligent guess"`) | 48 numUploadProcesses = flag.Int("upload_processes", 0, `The number of pr
ocesses to upload fuzzes [per fuzz to run]. Defaults to 0, which means "Make an
intelligent guess"`) |
48 statusPeriod = flag.Duration("status_period", 60*time.Second, `T
he time period used to report the status of the aggregation/analysis/upload queu
e. `) | 49 statusPeriod = flag.Duration("status_period", 60*time.Second, `T
he time period used to report the status of the aggregation/analysis/upload queu
e. `) |
49 analysisTimeout = flag.Duration("analysis_timeout", 5*time.Second,
`The maximum time an analysis should run.`) | 50 analysisTimeout = flag.Duration("analysis_timeout", 5*time.Second,
`The maximum time an analysis should run.`) |
50 | 51 |
51 » graphiteServer = flag.String("graphite_server", "localhost:2003", "Where
is Graphite metrics ingestion server running.") | 52 » influxHost = flag.String("influxdb_host", influxdb.DEFAULT_HOST, "Th
e InfluxDB hostname.") |
| 53 » influxUser = flag.String("influxdb_name", influxdb.DEFAULT_USER, "Th
e InfluxDB username.") |
| 54 » influxPassword = flag.String("influxdb_password", influxdb.DEFAULT_PASSW
ORD, "The InfluxDB password.") |
| 55 » influxDatabase = flag.String("influxdb_database", influxdb.DEFAULT_DATAB
ASE, "The InfluxDB database.") |
52 | 56 |
53 watchAFL = flag.Bool("watch_afl", false, "(debug only) If the afl
master's output should be piped to stdout.") | 57 watchAFL = flag.Bool("watch_afl", false, "(debug only) If the afl
master's output should be piped to stdout.") |
54 skipGeneration = flag.Bool("skip_generation", false, "(debug only) If t
he generation step should be disabled.") | 58 skipGeneration = flag.Bool("skip_generation", false, "(debug only) If t
he generation step should be disabled.") |
55 » forceReanalysis = flag.Bool("force_reanalysis", false, "(debug only) If
the fuzzes should be downloaded, re-analyzed, (deleted for GCS), and reuploaded.
") | 59 » forceReanalysis = flag.Bool("force_reanalysis", false, "(debug only) If
the fuzzes should be downloaded, re-analyzed, (deleted from GCS), and reuploaded
.") |
56 verboseBuilds = flag.Bool("verbose_builds", false, "If output from nin
ja and gyp should be printed to stdout.") | 60 verboseBuilds = flag.Bool("verbose_builds", false, "If output from nin
ja and gyp should be printed to stdout.") |
| 61 local = flag.Bool("local", false, "Running locally if true. As
opposed to in production.") |
57 ) | 62 ) |
58 | 63 |
59 var ( | 64 var ( |
60 requiredFlags = []string{"afl_output_path", "skia_root",
"clang_path", "clang_p_p_path", "afl_root", "generator_working_dir", "fuzz_to_r
un"} | 65 requiredFlags = []string{"afl_output_path", "skia_root",
"clang_path", "clang_p_p_path", "afl_root", "generator_working_dir", "fuzz_to_r
un"} |
61 storageClient *storage.Client = nil | 66 storageClient *storage.Client = nil |
62 ) | 67 ) |
63 | 68 |
64 func main() { | 69 func main() { |
65 defer common.LogPanic() | 70 defer common.LogPanic() |
66 // Calls flag.Parse() | 71 // Calls flag.Parse() |
67 » common.InitWithMetrics("fuzzer-be", graphiteServer) | 72 » common.InitWithMetrics2("fuzzer-be", influxHost, influxUser, influxPassw
ord, influxDatabase, local) |
68 | 73 |
69 if err := writeFlagsToConfig(); err != nil { | 74 if err := writeFlagsToConfig(); err != nil { |
70 glog.Fatalf("Problem with configuration: %v", err) | 75 glog.Fatalf("Problem with configuration: %v", err) |
71 } | 76 } |
72 if err := setupOAuth(); err != nil { | 77 if err := setupOAuth(); err != nil { |
73 glog.Fatalf("Problem with OAuth: %s", err) | 78 glog.Fatalf("Problem with OAuth: %s", err) |
74 } | 79 } |
75 if err := fcommon.DownloadSkiaVersionForFuzzing(storageClient, config.Ge
nerator.SkiaRoot, &config.Generator); err != nil { | 80 if err := fcommon.DownloadSkiaVersionForFuzzing(storageClient, config.Ge
nerator.SkiaRoot, &config.Generator); err != nil { |
76 glog.Fatalf("Problem downloading Skia: %s", err) | 81 glog.Fatalf("Problem downloading Skia: %s", err) |
77 } | 82 } |
78 | 83 |
79 fuzzPipelines := make([]backend.FuzzPipeline, 0, len(*fuzzesToRun)) | 84 fuzzPipelines := make([]backend.FuzzPipeline, 0, len(*fuzzesToRun)) |
80 | 85 |
81 for _, category := range *fuzzesToRun { | 86 for _, category := range *fuzzesToRun { |
82 gen := generator.New(category) | 87 gen := generator.New(category) |
83 if err := gen.DownloadSeedFiles(storageClient); err != nil { | 88 if err := gen.DownloadSeedFiles(storageClient); err != nil { |
84 glog.Fatalf("Problem downloading binary seed files: %s",
err) | 89 glog.Fatalf("Problem downloading binary seed files: %s",
err) |
85 } | 90 } |
86 | 91 |
87 // If we are reanalyzing, no point in running the generator firs
t, just to stop it. | 92 // If we are reanalyzing, no point in running the generator firs
t, just to stop it. |
88 » » if !*skipGeneration && !*forceReanalysis { | 93 » » if !*forceReanalysis { |
89 glog.Infof("Starting %s generator with configuration %#v
", category, config.Generator) | 94 glog.Infof("Starting %s generator with configuration %#v
", category, config.Generator) |
90 if err := gen.Start(); err != nil { | 95 if err := gen.Start(); err != nil { |
91 glog.Fatalf("Problem starting binary generator:
%s", err) | 96 glog.Fatalf("Problem starting binary generator:
%s", err) |
92 } | 97 } |
93 } else { | 98 } else { |
94 glog.Infof("Skipping %s generator because --skip_generat
ion is enabled", category) | 99 glog.Infof("Skipping %s generator because --skip_generat
ion is enabled", category) |
95 } | 100 } |
96 | 101 |
97 glog.Infof("Starting %s aggregator with configuration %#v", cate
gory, config.Aggregator) | 102 glog.Infof("Starting %s aggregator with configuration %#v", cate
gory, config.Aggregator) |
98 agg, err := aggregator.StartAggregator(storageClient, category) | 103 agg, err := aggregator.StartAggregator(storageClient, category) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 client, err := auth.NewDefaultJWTServiceAccountClient(auth.SCOPE_READ_WR
ITE) | 187 client, err := auth.NewDefaultJWTServiceAccountClient(auth.SCOPE_READ_WR
ITE) |
183 if err != nil { | 188 if err != nil { |
184 return fmt.Errorf("Problem setting up client OAuth: %v", err) | 189 return fmt.Errorf("Problem setting up client OAuth: %v", err) |
185 } | 190 } |
186 | 191 |
187 if storageClient, err = storage.NewClient(context.Background(), cloud.Wi
thBaseHTTP(client)); err != nil { | 192 if storageClient, err = storage.NewClient(context.Background(), cloud.Wi
thBaseHTTP(client)); err != nil { |
188 return fmt.Errorf("Problem authenticating: %v", err) | 193 return fmt.Errorf("Problem authenticating: %v", err) |
189 } | 194 } |
190 return nil | 195 return nil |
191 } | 196 } |
OLD | NEW |