mirror of
https://github.com/containerd/containerd.git
synced 2026-07-09 16:17:50 +00:00
Merge pull request #11251 from djdongjin/move-fuzz-to-go-native-2
Move all fuzz tests to go native fuzz [part2]
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
//go:build gofuzz
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -18,6 +16,8 @@ package fuzz
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/AdaLogics/go-fuzz-headers"
|
||||
|
||||
@@ -31,30 +31,35 @@ func fuzzContext() (context.Context, context.CancelFunc) {
|
||||
return ctx, cancel
|
||||
}
|
||||
|
||||
func FuzzContainerdImport(data []byte) int {
|
||||
initDaemon.Do(startDaemon)
|
||||
|
||||
client, err := containerd.New(defaultAddress)
|
||||
if err != nil {
|
||||
return 0
|
||||
func FuzzContainerdImport(f *testing.F) {
|
||||
if os.Getuid() != 0 {
|
||||
f.Skip("skipping fuzz test that requires root")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
initDaemon.Do(startDaemon)
|
||||
|
||||
noOfImports, err := f.GetInt()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
maxImports := 20
|
||||
ctx, cancel := fuzzContext()
|
||||
defer cancel()
|
||||
for i := 0; i < noOfImports%maxImports; i++ {
|
||||
tarBytes, err := f.GetBytes()
|
||||
client, err := containerd.New(defaultAddress)
|
||||
if err != nil {
|
||||
return 0
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, _ = client.Import(ctx, bytes.NewReader(tarBytes))
|
||||
}
|
||||
return 1
|
||||
defer client.Close()
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
|
||||
noOfImports, err := f.GetInt()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
maxImports := 20
|
||||
ctx, cancel := fuzzContext()
|
||||
defer cancel()
|
||||
for i := 0; i < noOfImports%maxImports; i++ {
|
||||
tarBytes, err := f.GetBytes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, _ = client.Import(ctx, bytes.NewReader(tarBytes))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:build gofuzz
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -18,46 +16,93 @@ package fuzz
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
golangruntime "runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
fuzz "github.com/AdaLogics/go-fuzz-headers"
|
||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
|
||||
containerd "github.com/containerd/containerd/v2/client"
|
||||
criconfig "github.com/containerd/containerd/v2/internal/cri/config"
|
||||
"github.com/containerd/containerd/v2/internal/cri/instrument"
|
||||
"github.com/containerd/containerd/v2/internal/cri/server"
|
||||
sandboxstore "github.com/containerd/containerd/v2/internal/cri/store/sandbox"
|
||||
"github.com/containerd/containerd/v2/internal/cri/server/images"
|
||||
"github.com/containerd/containerd/v2/pkg/oci"
|
||||
"github.com/containerd/errdefs"
|
||||
"google.golang.org/grpc"
|
||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
)
|
||||
|
||||
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",
|
||||
func FuzzCRIServer(f *testing.F) {
|
||||
if os.Getuid() != 0 {
|
||||
f.Skip("skipping fuzz test that requires root")
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
initDaemon.Do(startDaemon)
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
|
||||
client, err := containerd.New(defaultAddress)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
imageConfig := criconfig.ImageConfig{}
|
||||
|
||||
imageService, err := images.NewService(imageConfig, &images.CRIImageServiceOptions{
|
||||
Client: client,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
c, rs, err := server.NewCRIService(&server.CRIServiceOptions{
|
||||
RuntimeService: &fakeRuntimeService{},
|
||||
ImageService: imageService,
|
||||
Client: client,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fuzzCRI(t, f, &service{
|
||||
CRIService: c,
|
||||
RuntimeServiceServer: rs,
|
||||
ImageServiceServer: imageService.GRPCService(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type fakeRuntimeService struct{}
|
||||
|
||||
func (fakeRuntimeService) Config() criconfig.Config {
|
||||
return criconfig.Config{}
|
||||
}
|
||||
|
||||
func (fakeRuntimeService) LoadOCISpec(string) (*oci.Spec, error) {
|
||||
return nil, errdefs.ErrNotFound
|
||||
}
|
||||
|
||||
type service struct {
|
||||
server.CRIService
|
||||
runtime.RuntimeServiceServer
|
||||
runtime.ImageServiceServer
|
||||
}
|
||||
|
||||
func (c *service) Register(s *grpc.Server) error {
|
||||
instrumented := instrument.NewService(c)
|
||||
runtime.RegisterRuntimeServiceServer(s, instrumented)
|
||||
runtime.RegisterImageServiceServer(s, instrumented)
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
executionOrder []string
|
||||
)
|
||||
|
||||
func printExecutions() {
|
||||
func printExecutions(t *testing.T) {
|
||||
if r := recover(); r != nil {
|
||||
var err string
|
||||
switch res := r.(type) {
|
||||
@@ -70,11 +115,11 @@ func printExecutions() {
|
||||
default:
|
||||
err = "uknown error type"
|
||||
}
|
||||
fmt.Println("Executions:")
|
||||
t.Log("Executions:")
|
||||
for _, eo := range executionOrder {
|
||||
fmt.Println(eo)
|
||||
t.Log(eo)
|
||||
}
|
||||
panic(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,68 +129,45 @@ type fuzzCRIService interface {
|
||||
runtime.ImageServiceServer
|
||||
}
|
||||
|
||||
func fuzzCRI(f *fuzz.ConsumeFuzzer, c fuzzCRIService) int {
|
||||
func fuzzCRI(t *testing.T, f *fuzz.ConsumeFuzzer, c fuzzCRIService) int {
|
||||
ops := []func(c fuzzCRIService, f *fuzz.ConsumeFuzzer) error{
|
||||
createContainerFuzz,
|
||||
removeContainerFuzz,
|
||||
listContainersFuzz,
|
||||
startContainerFuzz,
|
||||
containerStatsFuzz,
|
||||
listContainerStatsFuzz,
|
||||
containerStatusFuzz,
|
||||
stopContainerFuzz,
|
||||
updateContainerResourcesFuzz,
|
||||
listImagesFuzz,
|
||||
removeImagesFuzz,
|
||||
imageStatusFuzz,
|
||||
imageFsInfoFuzz,
|
||||
listPodSandboxFuzz,
|
||||
portForwardFuzz,
|
||||
removePodSandboxFuzz,
|
||||
runPodSandboxFuzz,
|
||||
podSandboxStatusFuzz,
|
||||
stopPodSandboxFuzz,
|
||||
statusFuzz,
|
||||
updateRuntimeConfigFuzz,
|
||||
}
|
||||
|
||||
calls, err := f.GetInt()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
executionOrder = make([]string, 0)
|
||||
defer printExecutions()
|
||||
defer printExecutions(t)
|
||||
|
||||
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)
|
||||
}
|
||||
ops[op%len(ops)](c, f)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
@@ -184,67 +206,6 @@ func removeContainerFuzz(c fuzzCRIService, f *fuzz.ConsumeFuzzer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func sandboxStore(cs fuzzCRIService) (*sandboxstore.Store, error) {
|
||||
var (
|
||||
ss *sandboxstore.Store
|
||||
err error
|
||||
)
|
||||
|
||||
ss, err = server.SandboxStore(cs)
|
||||
if err != nil {
|
||||
ss, err = server.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 fuzzCRIService, 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 fuzzCRIService, f *fuzz.ConsumeFuzzer) error {
|
||||
@@ -1,92 +0,0 @@
|
||||
//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 (
|
||||
fuzz "github.com/AdaLogics/go-fuzz-headers"
|
||||
"google.golang.org/grpc"
|
||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
|
||||
containerd "github.com/containerd/containerd/v2/client"
|
||||
criconfig "github.com/containerd/containerd/v2/internal/cri/config"
|
||||
"github.com/containerd/containerd/v2/internal/cri/instrument"
|
||||
"github.com/containerd/containerd/v2/internal/cri/server"
|
||||
"github.com/containerd/containerd/v2/internal/cri/server/images"
|
||||
"github.com/containerd/containerd/v2/pkg/oci"
|
||||
"github.com/containerd/errdefs"
|
||||
)
|
||||
|
||||
func FuzzCRIServer(data []byte) int {
|
||||
initDaemon.Do(startDaemon)
|
||||
|
||||
f := fuzz.NewConsumer(data)
|
||||
|
||||
client, err := containerd.New(defaultAddress)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
imageConfig := criconfig.ImageConfig{}
|
||||
|
||||
imageService, err := images.NewService(imageConfig, &images.CRIImageServiceOptions{
|
||||
Client: client,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c, rs, err := server.NewCRIService(&server.CRIServiceOptions{
|
||||
RuntimeService: &fakeRuntimeService{},
|
||||
ImageService: imageService,
|
||||
Client: client,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return fuzzCRI(f, &service{
|
||||
CRIService: c,
|
||||
RuntimeServiceServer: rs,
|
||||
ImageServiceServer: imageService.GRPCService(),
|
||||
})
|
||||
}
|
||||
|
||||
type fakeRuntimeService struct{}
|
||||
|
||||
func (fakeRuntimeService) Config() criconfig.Config {
|
||||
return criconfig.Config{}
|
||||
}
|
||||
|
||||
func (fakeRuntimeService) LoadOCISpec(string) (*oci.Spec, error) {
|
||||
return nil, errdefs.ErrNotFound
|
||||
}
|
||||
|
||||
type service struct {
|
||||
server.CRIService
|
||||
runtime.RuntimeServiceServer
|
||||
runtime.ImageServiceServer
|
||||
}
|
||||
|
||||
func (c *service) Register(s *grpc.Server) error {
|
||||
instrumented := instrument.NewService(c)
|
||||
runtime.RegisterRuntimeServiceServer(s, instrumented)
|
||||
runtime.RegisterImageServiceServer(s, instrumented)
|
||||
return nil
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
//go:build gofuzz
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
//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 server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containerd/containerd/v2/internal/cri/store/sandbox"
|
||||
)
|
||||
|
||||
func SandboxStore(cs CRIService) (*sandbox.Store, error) {
|
||||
s, ok := cs.(*criService)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%+v is not sbserver.criService", cs)
|
||||
}
|
||||
return s.sandboxStore, nil
|
||||
}
|
||||
Reference in New Issue
Block a user