Merge pull request #5840 from AdamKorcz/fuzz9

Fuzzing: Add experimental version of container fuzzer
This commit is contained in:
Phil Estes 2021-08-11 11:45:49 -04:00 committed by GitHub
commit 159c0f04e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 3 deletions

View File

@ -32,17 +32,88 @@ import (
"github.com/containerd/containerd/sys" "github.com/containerd/containerd/sys"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"time" "time"
) )
func init() { var (
err := updatePathEnv() haveDownloadedbinaries = false
haveExtractedBinaries = false
haveChangedPATH = false
haveInitialized = false
downloadLink = "https://github.com/containerd/containerd/releases/download/v1.5.4/containerd-1.5.4-linux-amd64.tar.gz"
downloadPath = "/tmp/containerd-1.5.4-linux-amd64.tar.gz"
binariesDir = "/tmp/containerd-binaries"
)
// downloadFile downloads a file from a url
func downloadFile(filepath string, url string) (err error) {
out, err := os.Create(filepath)
if err != nil { if err != nil {
fmt.Println(err) return err
} }
defer out.Close()
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}
// 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 {
// Download binaries
if !haveDownloadedbinaries {
err := downloadFile(downloadPath, downloadLink)
if err != nil {
panic(err)
}
haveDownloadedbinaries = true
}
// Extract binaries
if !haveExtractedBinaries {
err := os.MkdirAll(binariesDir, 0777)
if err != nil {
return true
}
cmd := exec.Command("tar", "xvf", downloadPath, "-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/bin:%s", binariesDir, oldPathEnv)
err := os.Setenv("PATH", newPathEnv)
if err != nil {
return true
}
haveChangedPATH = true
return true
}
haveInitialized = true
return false
} }
func tearDown() error { func tearDown() error {
@ -153,6 +224,7 @@ func updatePathEnv() error {
if err != nil { if err != nil {
return err return err
} }
haveInitialized = true
return nil return nil
} }
@ -327,12 +399,39 @@ func doFuzz(data []byte, shouldTearDown bool) int {
return 1 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 // FuzzCreateContainerNoTearDown() implements a fuzzer
// similar to FuzzCreateContainerWithTearDown() with // similar to FuzzCreateContainerWithTearDown() with
// with one minor distinction: One tears down the // with one minor distinction: One tears down the
// daemon after each iteration whereas the other doesn't. // daemon after each iteration whereas the other doesn't.
// The two fuzzers' performance will be compared over time. // The two fuzzers' performance will be compared over time.
func FuzzCreateContainerNoTearDown(data []byte) int { func FuzzCreateContainerNoTearDown(data []byte) int {
if !haveInitialized {
err := updatePathEnv()
if err != nil {
return 0
}
}
ret := doFuzz(data, false) ret := doFuzz(data, false)
return ret return ret
} }
@ -342,6 +441,12 @@ func FuzzCreateContainerNoTearDown(data []byte) int {
// FuzzCreateContainerWithTearDown tears down the daemon // FuzzCreateContainerWithTearDown tears down the daemon
// after each iteration. // after each iteration.
func FuzzCreateContainerWithTearDown(data []byte) int { func FuzzCreateContainerWithTearDown(data []byte) int {
if !haveInitialized {
err := updatePathEnv()
if err != nil {
return 0
}
}
ret := doFuzz(data, true) ret := doFuzz(data, true)
return ret return ret
} }

View File

@ -69,5 +69,7 @@ for i in $( ls *_test.go ); do mv $i ./${i%.*}_fuzz.go; done
# Remove windows test to avoid double declarations: # Remove windows test to avoid double declarations:
rm ./client_windows_test_fuzz.go rm ./client_windows_test_fuzz.go
rm ./helpers_windows_test_fuzz.go
compile_go_fuzzer . FuzzCreateContainerNoTearDown fuzz_create_container_no_teardown compile_go_fuzzer . FuzzCreateContainerNoTearDown fuzz_create_container_no_teardown
compile_go_fuzzer . FuzzCreateContainerWithTearDown fuzz_create_container_with_teardown compile_go_fuzzer . FuzzCreateContainerWithTearDown fuzz_create_container_with_teardown
compile_go_fuzzer . FuzzNoTearDownWithDownload fuzz_no_teardown_with_download