541 lines
14 KiB
Go
541 lines
14 KiB
Go
//go:build gofuzz
|
|
|
|
/*
|
|
Copyright The containerd Authors.
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package fuzz
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
golangruntime "runtime"
|
|
"strings"
|
|
|
|
fuzz "github.com/AdaLogics/go-fuzz-headers"
|
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
|
|
|
"github.com/containerd/containerd/pkg/cri/sbserver"
|
|
"github.com/containerd/containerd/pkg/cri/server"
|
|
containerstore "github.com/containerd/containerd/pkg/cri/store/container"
|
|
sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox"
|
|
)
|
|
|
|
var (
|
|
// The APIs the fuzzer can call:
|
|
ops = map[int]string{
|
|
0: "createContainer",
|
|
1: "removeContainer",
|
|
2: "addSandboxes",
|
|
3: "listContainers",
|
|
4: "startContainer",
|
|
5: "containerStats",
|
|
6: "listContainerStats",
|
|
7: "containerStatus",
|
|
8: "stopContainer",
|
|
9: "updateContainerResources",
|
|
10: "listImages",
|
|
11: "removeImages",
|
|
12: "imageStatus",
|
|
13: "imageFsInfo",
|
|
14: "listPodSandbox",
|
|
15: "portForward",
|
|
16: "removePodSandbox",
|
|
17: "runPodSandbox",
|
|
18: "podSandboxStatus",
|
|
19: "stopPodSandbox",
|
|
20: "status",
|
|
21: "updateRuntimeConfig",
|
|
}
|
|
executionOrder []string
|
|
)
|
|
|
|
func printExecutions() {
|
|
if r := recover(); r != nil {
|
|
var err string
|
|
switch r.(type) {
|
|
case string:
|
|
err = r.(string)
|
|
case golangruntime.Error:
|
|
err = r.(golangruntime.Error).Error()
|
|
case error:
|
|
err = r.(error).Error()
|
|
default:
|
|
err = "uknown error type"
|
|
}
|
|
fmt.Println("Executions:")
|
|
for _, eo := range executionOrder {
|
|
fmt.Println(eo)
|
|
}
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func fuzzCRI(f *fuzz.ConsumeFuzzer, c server.CRIService) int {
|
|
executionOrder = make([]string, 0)
|
|
defer printExecutions()
|
|
|
|
calls, err := f.GetInt()
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
|
|
executionOrder = make([]string, 0)
|
|
defer printExecutions()
|
|
|
|
for i := 0; i < calls%40; i++ {
|
|
op, err := f.GetInt()
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
opType := op % len(ops)
|
|
|
|
switch ops[opType] {
|
|
case "createContainer":
|
|
createContainerFuzz(c, f)
|
|
case "removeContainer":
|
|
removeContainerFuzz(c, f)
|
|
case "addSandboxes":
|
|
addSandboxesFuzz(c, f)
|
|
case "listContainers":
|
|
listContainersFuzz(c, f)
|
|
case "startContainer":
|
|
startContainerFuzz(c, f)
|
|
case "containerStats":
|
|
containerStatsFuzz(c, f)
|
|
case "listContainerStats":
|
|
listContainerStatsFuzz(c, f)
|
|
case "containerStatus":
|
|
containerStatusFuzz(c, f)
|
|
case "stopContainer":
|
|
stopContainerFuzz(c, f)
|
|
case "updateContainerResources":
|
|
updateContainerResourcesFuzz(c, f)
|
|
case "listImages":
|
|
listImagesFuzz(c, f)
|
|
case "removeImages":
|
|
removeImagesFuzz(c, f)
|
|
case "imageStatus":
|
|
imageStatusFuzz(c, f)
|
|
case "imageFsInfo":
|
|
imageFsInfoFuzz(c, f)
|
|
case "listPodSandbox":
|
|
listPodSandboxFuzz(c, f)
|
|
case "portForward":
|
|
portForwardFuzz(c, f)
|
|
case "removePodSandbox":
|
|
removePodSandboxFuzz(c, f)
|
|
case "runPodSandbox":
|
|
runPodSandboxFuzz(c, f)
|
|
case "podSandboxStatus":
|
|
podSandboxStatusFuzz(c, f)
|
|
case "stopPodSandbox":
|
|
stopPodSandboxFuzz(c, f)
|
|
case "status":
|
|
statusFuzz(c, f)
|
|
case "updateRuntimeConfig":
|
|
updateRuntimeConfigFuzz(c, f)
|
|
}
|
|
}
|
|
return 1
|
|
}
|
|
|
|
func logExecution(apiName, request string) {
|
|
var logString strings.Builder
|
|
logString.WriteString(fmt.Sprintf("Calling %s with \n %s \n\n", apiName, request))
|
|
executionOrder = append(executionOrder, logString.String())
|
|
}
|
|
|
|
// createContainerFuzz creates a CreateContainerRequest and passes
|
|
// it to c.CreateContainer
|
|
func createContainerFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.CreateContainerRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.CreateContainer(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.CreateContainer", reqString)
|
|
return nil
|
|
}
|
|
|
|
// removeContainerFuzz creates a RemoveContainerRequest and passes
|
|
// it to c.RemoveContainer
|
|
func removeContainerFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.RemoveContainerRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.RemoveContainer(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.RemoveContainer", reqString)
|
|
return nil
|
|
}
|
|
|
|
func sandboxStore(cs server.CRIService) (*sandboxstore.Store, error) {
|
|
var (
|
|
ss *sandboxstore.Store
|
|
err error
|
|
)
|
|
|
|
ss, err = server.SandboxStore(cs)
|
|
if err != nil {
|
|
ss, err = sbserver.SandboxStore(cs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ss, nil
|
|
}
|
|
return ss, nil
|
|
}
|
|
|
|
// addSandboxesFuzz creates a sandbox and adds it to the sandboxstore
|
|
func addSandboxesFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
quantity, err := f.GetInt()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ss, err := sandboxStore(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i := 0; i < quantity%20; i++ {
|
|
newSandbox, err := getSandboxFuzz(f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ss.Add(newSandbox)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// getSandboxFuzz creates a sandbox
|
|
func getSandboxFuzz(f *fuzz.ConsumeFuzzer) (sandboxstore.Sandbox, error) {
|
|
metadata := sandboxstore.Metadata{}
|
|
status := sandboxstore.Status{}
|
|
err := f.GenerateStruct(&metadata)
|
|
if err != nil {
|
|
return sandboxstore.Sandbox{}, err
|
|
}
|
|
err = f.GenerateStruct(&status)
|
|
if err != nil {
|
|
return sandboxstore.Sandbox{}, err
|
|
}
|
|
|
|
reqString := fmt.Sprintf("metadata: %+v\nstatus: %+v\n", metadata, status)
|
|
logExecution("sandboxstore.NewSandbox", reqString)
|
|
|
|
return sandboxstore.NewSandbox(metadata, status), nil
|
|
}
|
|
|
|
// listContainersFuzz creates a ListContainersRequest and passes
|
|
// it to c.ListContainers
|
|
func listContainersFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ListContainersRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ListContainers(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ListContainers", reqString)
|
|
return nil
|
|
}
|
|
|
|
// startContainerFuzz creates a StartContainerRequest and passes
|
|
// it to c.StartContainer
|
|
func startContainerFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.StartContainerRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.StartContainer(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.StartContainer", reqString)
|
|
return nil
|
|
}
|
|
|
|
// containerStatsFuzz creates a ContainerStatsRequest and passes
|
|
// it to c.ContainerStats
|
|
func containerStatsFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ContainerStatsRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ContainerStats(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ContainerStats", reqString)
|
|
return nil
|
|
}
|
|
|
|
// listContainerStatsFuzz creates a ListContainerStatsRequest and
|
|
// passes it to c.ListContainerStats
|
|
func listContainerStatsFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ListContainerStatsRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ListContainerStats(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ListContainerStats", reqString)
|
|
return nil
|
|
}
|
|
|
|
// containerStatusFuzz creates a ContainerStatusRequest and passes
|
|
// it to c.ContainerStatus
|
|
func containerStatusFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ContainerStatusRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ContainerStatus(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ContainerStatus", reqString)
|
|
return nil
|
|
}
|
|
|
|
// stopContainerFuzz creates a StopContainerRequest and passes
|
|
// it to c.StopContainer
|
|
func stopContainerFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.StopContainerRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.StopContainer(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.StopContainer", reqString)
|
|
return nil
|
|
}
|
|
|
|
// updateContainerResourcesFuzz creates a UpdateContainerResourcesRequest
|
|
// and passes it to c.UpdateContainerResources
|
|
func updateContainerResourcesFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.UpdateContainerResourcesRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.UpdateContainerResources(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.UpdateContainerResources", reqString)
|
|
return nil
|
|
}
|
|
|
|
// listImagesFuzz creates a ListImagesRequest and passes it to
|
|
// c.ListImages
|
|
func listImagesFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ListImagesRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ListImages(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ListImages", reqString)
|
|
return nil
|
|
}
|
|
|
|
// removeImagesFuzz creates a RemoveImageRequest and passes it to
|
|
// c.RemoveImage
|
|
func removeImagesFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.RemoveImageRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.RemoveImage(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.RemoveImage", reqString)
|
|
return nil
|
|
}
|
|
|
|
// imageStatusFuzz creates an ImageStatusRequest and passes it to
|
|
// c.ImageStatus
|
|
func imageStatusFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ImageStatusRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ImageStatus(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ImageStatus", reqString)
|
|
return nil
|
|
}
|
|
|
|
// imageFsInfoFuzz creates an ImageFsInfoRequest and passes it to
|
|
// c.ImageFsInfo
|
|
func imageFsInfoFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ImageFsInfoRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ImageFsInfo(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ImageFsInfo", reqString)
|
|
return nil
|
|
}
|
|
|
|
// listPodSandboxFuzz creates a ListPodSandboxRequest and passes
|
|
// it to c.ListPodSandbox
|
|
func listPodSandboxFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.ListPodSandboxRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.ListPodSandbox(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.ListPodSandbox", reqString)
|
|
return nil
|
|
}
|
|
|
|
// portForwardFuzz creates a PortForwardRequest and passes it to
|
|
// c.PortForward
|
|
func portForwardFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.PortForwardRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.PortForward(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.PortForward", reqString)
|
|
return nil
|
|
}
|
|
|
|
// removePodSandboxFuzz creates a RemovePodSandboxRequest and
|
|
// passes it to c.RemovePodSandbox
|
|
func removePodSandboxFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.RemovePodSandboxRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.RemovePodSandbox(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.RemovePodSandbox", reqString)
|
|
return nil
|
|
}
|
|
|
|
// runPodSandboxFuzz creates a RunPodSandboxRequest and passes
|
|
// it to c.RunPodSandbox
|
|
func runPodSandboxFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.RunPodSandboxRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.RunPodSandbox(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.RunPodSandbox", reqString)
|
|
return nil
|
|
}
|
|
|
|
// podSandboxStatusFuzz creates a PodSandboxStatusRequest and
|
|
// passes it to
|
|
func podSandboxStatusFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.PodSandboxStatusRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.PodSandboxStatus(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.PodSandboxStatus", reqString)
|
|
return nil
|
|
}
|
|
|
|
// stopPodSandboxFuzz creates a StopPodSandboxRequest and passes
|
|
// it to c.StopPodSandbox
|
|
func stopPodSandboxFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.StopPodSandboxRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.StopPodSandbox(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.StopPodSandbox", reqString)
|
|
return nil
|
|
}
|
|
|
|
// statusFuzz creates a StatusRequest and passes it to c.Status
|
|
func statusFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.StatusRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.Status(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.Status", reqString)
|
|
return nil
|
|
}
|
|
|
|
func updateRuntimeConfigFuzz(c server.CRIService, f *fuzz.ConsumeFuzzer) error {
|
|
r := &runtime.UpdateRuntimeConfigRequest{}
|
|
err := f.GenerateStruct(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = c.UpdateRuntimeConfig(context.Background(), r)
|
|
reqString := fmt.Sprintf("%+v", r)
|
|
logExecution("c.UpdateRuntimeConfig", reqString)
|
|
return nil
|
|
}
|
|
|
|
// This creates a container directly in the store.
|
|
func getContainer(f *fuzz.ConsumeFuzzer) (containerstore.Container, error) {
|
|
metadata := containerstore.Metadata{}
|
|
status := containerstore.Status{}
|
|
|
|
err := f.GenerateStruct(&metadata)
|
|
if err != nil {
|
|
return containerstore.Container{}, err
|
|
}
|
|
err = f.GenerateStruct(&status)
|
|
if err != nil {
|
|
return containerstore.Container{}, err
|
|
}
|
|
container, err := containerstore.NewContainer(metadata, containerstore.WithFakeStatus(status))
|
|
return container, err
|
|
}
|
|
|
|
func FuzzParseAuth(data []byte) int {
|
|
f := fuzz.NewConsumer(data)
|
|
auth := &runtime.AuthConfig{}
|
|
err := f.GenerateStruct(auth)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
host, err := f.GetString()
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
_, _, _ = server.ParseAuth(auth, host)
|
|
return 1
|
|
}
|