diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-11-25 11:55:32 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-11-25 11:22:38 +0000 |
| commit | a84878fcfef572bb166d73bcc5974ea50a3fde64 (patch) | |
| tree | 89f9ecd7f017517770ece33ac7df36e632c0562c /syz-manager | |
| parent | 7e02dfac6584de88e03df494ca500b59802d93eb (diff) | |
syz-manager: refactor mode handling
Makes modes more scalable and easier to add.
Currently the name, descritpion, and logic for each mode
is spread across the code.
Make most things related to a mode described in the mode
description, but also possible to check for a concrete
mode in the code if necessary.
Diffstat (limited to 'syz-manager')
| -rw-r--r-- | syz-manager/manager.go | 134 |
1 files changed, 81 insertions, 53 deletions
diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 7a82a4ee7..4feb3214b 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -52,26 +52,13 @@ var ( flagConfig = flag.String("config", "", "configuration file") flagDebug = flag.Bool("debug", false, "dump all VM output to console") flagBench = flag.String("bench", "", "write execution statistics into this file periodically") - - flagMode = flag.String("mode", "fuzzing", "mode of operation, one of:\n"+ - " - fuzzing: the default continuous fuzzing mode\n"+ - " - smoke-test: run smoke test for syzkaller+kernel\n"+ - " The test consists of booting VMs and running some simple test programs\n"+ - " to ensure that fuzzing can proceed in general. After completing the test\n"+ - " the process exits and the exit status indicates success/failure.\n"+ - " If the kernel oopses during testing, the report is saved to workdir/report.json.\n"+ - " - corpus-triage: triage corpus and exit\n"+ - " This is useful mostly for benchmarking with testbed.\n"+ - " - corpus-run: continuously run the corpus programs.\n"+ - " - run-tests: run unit tests\n"+ - " Run sys/os/test/* tests in various modes and print results.\n") - - flagTests = flag.String("tests", "", "prefix to match test file names (for -mode run-tests)") + flagMode = flag.String("mode", ModeFuzzing.Name, modesDescription()) + flagTests = flag.String("tests", "", "prefix to match test file names (for -mode run-tests)") ) type Manager struct { cfg *mgrconfig.Config - mode Mode + mode *Mode vmPool *vm.Pool pool *vm.Dispatcher target *prog.Target @@ -123,17 +110,67 @@ type Manager struct { Stats } -type Mode int +type Mode struct { + Name string + Description string + UseDashboard bool // the mode connects to dashboard/hub + LoadCorpus bool // the mode needs to load the corpus + ExitAfterMachineCheck bool // exit with 0 status when machine check is done + // Exit with non-zero status and save the report to workdir/report.json if any kernel crash happens. + FailOnCrashes bool +} -// For description of modes see flagMode help. -const ( - ModeFuzzing Mode = iota - ModeSmokeTest - ModeCorpusTriage - ModeCorpusRun - ModeRunTests +var ( + ModeFuzzing = &Mode{ + Name: "fuzzing", + Description: `the default continuous fuzzing mode`, + UseDashboard: true, + LoadCorpus: true, + } + ModeSmokeTest = &Mode{ + Name: "smoke-test", + Description: `run smoke test for syzkaller+kernel + The test consists of booting VMs and running some simple test programs + to ensure that fuzzing can proceed in general. After completing the test + the process exits and the exit status indicates success/failure. + If the kernel oopses during testing, the report is saved to workdir/report.json.`, + ExitAfterMachineCheck: true, + FailOnCrashes: true, + } + ModeCorpusTriage = &Mode{ + Name: "corpus-triage", + Description: `triage corpus and exit + This is useful mostly for benchmarking with testbed.`, + LoadCorpus: true, + } + ModeCorpusRun = &Mode{ + Name: "corpus-run", + Description: `continuously run the corpus programs`, + LoadCorpus: true, + } + ModeRunTests = &Mode{ + Name: "run-tests", + Description: `run unit tests + Run sys/os/test/* tests in various modes and print results.`, + } + + modes = []*Mode{ + ModeFuzzing, + ModeSmokeTest, + ModeCorpusTriage, + ModeCorpusRun, + ModeRunTests, + } ) +func modesDescription() string { + desc := "mode of operation, one of:\n" + for _, mode := range modes { + desc += fmt.Sprintf(" - %v: %v\n", mode.Name, mode.Description) + } + return desc +} + const ( // Just started, nothing done yet. phaseInit = iota @@ -150,10 +187,10 @@ const ( ) func main() { + flag.Parse() if !prog.GitRevisionKnown() { log.Fatalf("bad syz-manager build: build with make, run bin/syz-manager") } - flag.Parse() log.EnableLogCaching(1000, 1<<20) cfg, err := mgrconfig.LoadFile(*flagConfig) if err != nil { @@ -163,34 +200,25 @@ func main() { // This lets better distinguish logs of individual syz-manager instances. log.SetName(cfg.Name) } - var mode Mode - switch *flagMode { - case "fuzzing": - mode = ModeFuzzing - case "smoke-test": - mode = ModeSmokeTest - cfg.DashboardClient = "" - cfg.HubClient = "" - case "corpus-triage": - mode = ModeCorpusTriage - cfg.DashboardClient = "" - cfg.HubClient = "" - case "corpus-run": - mode = ModeCorpusRun - cfg.HubClient = "" - cfg.DashboardClient = "" - case "run-tests": - mode = ModeRunTests - cfg.DashboardClient = "" - cfg.HubClient = "" - default: + var mode *Mode + for _, m := range modes { + if *flagMode == m.Name { + mode = m + break + } + } + if mode == nil { flag.PrintDefaults() log.Fatalf("unknown mode: %v", *flagMode) } + if !mode.UseDashboard { + cfg.DashboardClient = "" + cfg.HubClient = "" + } RunManager(mode, cfg) } -func RunManager(mode Mode, cfg *mgrconfig.Config) { +func RunManager(mode *Mode, cfg *mgrconfig.Config) { var vmPool *vm.Pool if !cfg.VMLess { var err error @@ -237,7 +265,7 @@ func RunManager(mode Mode, cfg *mgrconfig.Config) { } mgr.initStats() - if mode == ModeFuzzing || mode == ModeCorpusTriage || mode == ModeCorpusRun { + if mgr.mode.LoadCorpus { go mgr.preloadCorpus() } else { close(mgr.corpusPreload) @@ -630,7 +658,7 @@ func (mgr *Manager) saveCrash(crash *manager.Crash) bool { } log.Logf(0, "VM %v: crash: %v%v", crash.InstanceIndex, crash.Title, flags) - if mgr.mode == ModeSmokeTest { + if mgr.mode.FailOnCrashes { data, err := json.Marshal(crash.Report) if err != nil { log.Fatalf("failed to serialize crash report: %v", err) @@ -1015,8 +1043,8 @@ func (mgr *Manager) MachineChecked(features flatrpc.Feature, enabledSyscalls map if len(enabledSyscalls) == 0 { log.Fatalf("all system calls are disabled") } - if mgr.mode == ModeSmokeTest { - mgr.exit("smoke test") + if mgr.mode.ExitAfterMachineCheck { + mgr.exit("done") } mgr.mu.Lock() @@ -1037,7 +1065,7 @@ func (mgr *Manager) MachineChecked(features flatrpc.Feature, enabledSyscalls map mgr.setPhaseLocked(phaseLoadedCorpus) opts := fuzzer.DefaultExecOpts(mgr.cfg, features, *flagDebug) - if mgr.mode == ModeFuzzing { + if mgr.mode == ModeFuzzing || mgr.mode == ModeCorpusTriage { corpusUpdates := make(chan corpus.NewItemEvent, 128) mgr.corpus = corpus.NewFocusedCorpus(context.Background(), corpusUpdates, mgr.coverFilters.Areas) @@ -1120,7 +1148,7 @@ func (mgr *Manager) MachineChecked(features flatrpc.Feature, enabledSyscalls map }() return ctx } - panic(fmt.Sprintf("unexpected mode %q", mgr.mode)) + panic(fmt.Sprintf("unexpected mode %q", mgr.mode.Name)) } type corpusRunner struct { |
