| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 } | 150 } |
| 146 | 151 |
| 147 config.Common.VerboseBuilds = *verboseBuilds | 152 config.Common.VerboseBuilds = *verboseBuilds |
| 148 config.Common.ClangPath = *clangPath | 153 config.Common.ClangPath = *clangPath |
| 149 config.Common.ClangPlusPlusPath = *clangPlusPlusPath | 154 config.Common.ClangPlusPlusPath = *clangPlusPlusPath |
| 150 config.Common.DepotToolsPath = *depotToolsPath | 155 config.Common.DepotToolsPath = *depotToolsPath |
| 151 config.Generator.NumFuzzProcesses = *numFuzzProcesses | 156 config.Generator.NumFuzzProcesses = *numFuzzProcesses |
| 152 config.Generator.WatchAFL = *watchAFL | 157 config.Generator.WatchAFL = *watchAFL |
| 153 config.Generator.VersionCheckPeriod = *versionCheckPeriod | 158 config.Generator.VersionCheckPeriod = *versionCheckPeriod |
| 154 config.Generator.NumDownloadProcesses = *downloadProcesses | 159 config.Generator.NumDownloadProcesses = *downloadProcesses |
| 160 config.Generator.SkipGeneration = *skipGeneration |
| 155 | 161 |
| 156 config.GS.Bucket = *bucket | 162 config.GS.Bucket = *bucket |
| 157 config.Aggregator.FuzzPath, err = fileutil.EnsureDirExists(*fuzzPath) | 163 config.Aggregator.FuzzPath, err = fileutil.EnsureDirExists(*fuzzPath) |
| 158 if err != nil { | 164 if err != nil { |
| 159 return err | 165 return err |
| 160 } | 166 } |
| 161 config.Aggregator.ExecutablePath, err = fileutil.EnsureDirExists(*execut
ablePath) | 167 config.Aggregator.ExecutablePath, err = fileutil.EnsureDirExists(*execut
ablePath) |
| 162 if err != nil { | 168 if err != nil { |
| 163 return err | 169 return err |
| 164 } | 170 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 182 client, err := auth.NewDefaultJWTServiceAccountClient(auth.SCOPE_READ_WR
ITE) | 188 client, err := auth.NewDefaultJWTServiceAccountClient(auth.SCOPE_READ_WR
ITE) |
| 183 if err != nil { | 189 if err != nil { |
| 184 return fmt.Errorf("Problem setting up client OAuth: %v", err) | 190 return fmt.Errorf("Problem setting up client OAuth: %v", err) |
| 185 } | 191 } |
| 186 | 192 |
| 187 if storageClient, err = storage.NewClient(context.Background(), cloud.Wi
thBaseHTTP(client)); err != nil { | 193 if storageClient, err = storage.NewClient(context.Background(), cloud.Wi
thBaseHTTP(client)); err != nil { |
| 188 return fmt.Errorf("Problem authenticating: %v", err) | 194 return fmt.Errorf("Problem authenticating: %v", err) |
| 189 } | 195 } |
| 190 return nil | 196 return nil |
| 191 } | 197 } |
| OLD | NEW |