diff --git a/contrib/fuzz/container_fuzzer.go b/contrib/fuzz/container_fuzzer.go index 0ed750159..ed3fa9a6d 100644 --- a/contrib/fuzz/container_fuzzer.go +++ b/contrib/fuzz/container_fuzzer.go @@ -38,11 +38,69 @@ import ( "time" ) -func init() { - err := updatePathEnv() - if err != nil { - fmt.Println(err) +var ( + haveInstalledWget = false + haveDownloadedbinaries = false + haveExtractedBinaries = false + haveChangedPATH = false + haveInitialized = false +) + +// initInSteps() performs initialization in several steps +// The reason for spreading the initialization out in +// multiple steps is that each fuzz iteration can maximum +// take 25 seconds when running through OSS-fuzz. +// Should an iteration exceed that, then the fuzzer stops. +func initInSteps() bool { + // Install wget + if !haveInstalledWget { + cmd := exec.Command("apt-get", "install", "-y", "wget") + err := cmd.Run() + if err != nil { + return true + } + haveInstalledWget = true + return true } + // Download binaries + if !haveDownloadedbinaries { + tarLink := "https://github.com/containerd/containerd/releases/download/v1.5.4/containerd-1.5.4-linux-amd64.tar.gz" + cmd := exec.Command("wget", tarLink) + err := cmd.Run() + if err != nil { + return true + } + haveDownloadedbinaries = true + return true + } + // Extract binaries + binariesDir := "/tmp/containerd-binaries" + if !haveExtractedBinaries { + err := os.MkdirAll(binariesDir, 0777) + if err != nil { + return true + } + cmd := exec.Command("tar", "xvf", "containerd-1.5.4-linux-amd64.tar.gz", "-C", binariesDir) + err = cmd.Run() + if err != nil { + return true + } + haveExtractedBinaries = true + return true + } + // Add binaries to $PATH: + if !haveChangedPATH { + oldPathEnv := os.Getenv("PATH") + newPathEnv := fmt.Sprintf("%s:%s/bin", oldPathEnv, binariesDir) + err := os.Setenv("PATH", newPathEnv) + if err != nil { + return true + } + haveChangedPATH = true + return true + } + haveInitialized = true + return false } func tearDown() error { @@ -153,6 +211,7 @@ func updatePathEnv() error { if err != nil { return err } + haveInitialized = true return nil } @@ -327,12 +386,39 @@ func doFuzz(data []byte, shouldTearDown bool) int { return 1 } +// FuzzCreateContainerNoTearDown() implements a fuzzer +// similar to FuzzCreateContainerWithTearDown() and +// FuzzCreateContainerWithTearDown(), but it takes a +// different approach to the initialization. Where +// the other 2 fuzzers depend on the containerd binaries +// that were built manually, this fuzzer downloads them +// when starting a fuzz run. +// This fuzzer is experimental for now and is being run +// continuously by OSS-fuzz to collect feedback on +// its sustainability. +func FuzzNoTearDownWithDownload(data []byte) int { + if !haveInitialized { + shouldRestart := initInSteps() + if shouldRestart { + return 0 + } + } + ret := doFuzz(data, false) + return ret +} + // FuzzCreateContainerNoTearDown() implements a fuzzer // similar to FuzzCreateContainerWithTearDown() with // with one minor distinction: One tears down the // daemon after each iteration whereas the other doesn't. // The two fuzzers' performance will be compared over time. func FuzzCreateContainerNoTearDown(data []byte) int { + if !haveInitialized { + err := updatePathEnv() + if err != nil { + return 0 + } + } ret := doFuzz(data, false) return ret } @@ -342,6 +428,12 @@ func FuzzCreateContainerNoTearDown(data []byte) int { // FuzzCreateContainerWithTearDown tears down the daemon // after each iteration. func FuzzCreateContainerWithTearDown(data []byte) int { + if !haveInitialized { + err := updatePathEnv() + if err != nil { + return 0 + } + } ret := doFuzz(data, true) return ret } diff --git a/contrib/fuzz/oss_fuzz_build.sh b/contrib/fuzz/oss_fuzz_build.sh index 62d8382f3..f4fe3d5ef 100755 --- a/contrib/fuzz/oss_fuzz_build.sh +++ b/contrib/fuzz/oss_fuzz_build.sh @@ -69,5 +69,7 @@ for i in $( ls *_test.go ); do mv $i ./${i%.*}_fuzz.go; done # Remove windows test to avoid double declarations: rm ./client_windows_test_fuzz.go +rm ./helpers_windows_test_fuzz.go compile_go_fuzzer . FuzzCreateContainerNoTearDown fuzz_create_container_no_teardown compile_go_fuzzer . FuzzCreateContainerWithTearDown fuzz_create_container_with_teardown +compile_go_fuzzer . FuzzNoTearDownWithDownload fuzz_no_teardown_with_download