From 420cb51b47e19556c35423354102fdc3a4d041f0 Mon Sep 17 00:00:00 2001 From: jikui Date: Fri, 5 Nov 2021 16:29:40 +0800 Subject: [PATCH] kata-runtime: validate sandbox cpu and memory size Signed-off-by: jikui --- src/runtime/pkg/katautils/config.go | 39 +++++++++++++++++-- src/runtime/pkg/katautils/config_test.go | 5 +-- src/runtime/virtcontainers/pkg/oci/utils.go | 10 ++--- src/runtime/virtcontainers/utils/utils.go | 42 +++++++++++++++++++++ 4 files changed, 85 insertions(+), 11 deletions(-) diff --git a/src/runtime/pkg/katautils/config.go b/src/runtime/pkg/katautils/config.go index e0ebc84..e523ed3 100644 --- a/src/runtime/pkg/katautils/config.go +++ b/src/runtime/pkg/katautils/config.go @@ -11,7 +11,6 @@ import ( "fmt" "io/ioutil" "path/filepath" - goruntime "runtime" "strings" "github.com/BurntSushi/toml" @@ -311,7 +310,7 @@ func (h hypervisor) GetEntropySource() string { } func (h hypervisor) defaultVCPUs() uint32 { - numCPUs := goruntime.NumCPU() + numCPUs := utils.GetPhysicalCPUNumber() if h.NumVCPUs < 0 || h.NumVCPUs > int32(numCPUs) { return uint32(numCPUs) @@ -323,8 +322,22 @@ func (h hypervisor) defaultVCPUs() uint32 { return uint32(h.NumVCPUs) } +func (h hypervisor) checkVCPUs() error { + numCPUs := utils.GetPhysicalCPUNumber() + + if h.NumVCPUs <= 0 { + return fmt.Errorf("invalid vcpus in configuration.toml! vcpus must larger than 0") + } + + if h.NumVCPUs > int32(numCPUs) { + return fmt.Errorf("invalid vcpus in configuration.toml! vcpus must smaller than max CPUs: %d in machine", numCPUs) + } + + return nil +} + func (h hypervisor) defaultMaxVCPUs() uint32 { - numcpus := uint32(goruntime.NumCPU()) + numcpus := uint32(utils.GetPhysicalCPUNumber()) maxvcpus := vc.MaxQemuVCPUs() reqVCPUs := h.DefaultMaxVCPUs @@ -350,6 +363,18 @@ func (h hypervisor) defaultMemSz() uint32 { return h.MemorySize } +func (h hypervisor) checkMemSz() error { + if h.MemorySize < utils.MinMemorySizeInMB { + return fmt.Errorf("invalid memory size! Memory size must larger than %d MB", utils.MinMemorySizeInMB) + } + + if h.MemorySize > utils.MaxMemorySizeInMB { + return fmt.Errorf("invalid memory size, memory size must smaller than %d MB", utils.MaxMemorySizeInMB) + } + + return nil +} + func (h hypervisor) defaultMemSlots() uint32 { slots := h.MemSlots if slots == 0 { @@ -665,6 +690,14 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) { return vc.HypervisorConfig{}, err } + if err = h.checkVCPUs(); err != nil { + return vc.HypervisorConfig{}, err + } + + if err = h.checkMemSz(); err != nil { + return vc.HypervisorConfig{}, err + } + rxRateLimiterMaxRate := h.getRxRateLimiterCfg() txRateLimiterMaxRate := h.getTxRateLimiterCfg() diff --git a/src/runtime/pkg/katautils/config_test.go b/src/runtime/pkg/katautils/config_test.go index 84b7843..3782268 100644 --- a/src/runtime/pkg/katautils/config_test.go +++ b/src/runtime/pkg/katautils/config_test.go @@ -14,7 +14,6 @@ import ( "path" "path/filepath" "reflect" - goruntime "runtime" "strings" "syscall" "testing" @@ -155,7 +154,7 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf KernelParams: vc.DeserializeParams(strings.Fields(kernelParams)), HypervisorMachineType: machineType, NumVCPUs: defaultVCPUCount, - DefaultMaxVCPUs: uint32(goruntime.NumCPU()), + DefaultMaxVCPUs: uint32(utils.GetPhysicalCPUNumber()), MemorySize: defaultMemSize, DisableBlockDeviceUse: disableBlockDevice, BlockDeviceDriver: defaultBlockDeviceDriver, @@ -918,7 +917,7 @@ func TestNewClhHypervisorConfig(t *testing.T) { func TestHypervisorDefaults(t *testing.T) { assert := assert.New(t) - numCPUs := goruntime.NumCPU() + numCPUs := utils.GetPhysicalCPUNumber() h := hypervisor{} diff --git a/src/runtime/virtcontainers/pkg/oci/utils.go b/src/runtime/virtcontainers/pkg/oci/utils.go index efaee4a..ea46ab7 100644 --- a/src/runtime/virtcontainers/pkg/oci/utils.go +++ b/src/runtime/virtcontainers/pkg/oci/utils.go @@ -12,15 +12,12 @@ import ( "fmt" "path/filepath" "regexp" - goruntime "runtime" "strconv" "strings" "syscall" criContainerdAnnotations "github.com/containerd/cri-containerd/pkg/annotations" crioAnnotations "github.com/cri-o/cri-o/pkg/annotations" - specs "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/resource" vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers" @@ -29,6 +26,9 @@ import ( vcAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations" dockershimAnnotations "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/annotations/dockershim" "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types" + "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils" + specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/sirupsen/logrus" ) type annotationContainerType struct { @@ -656,7 +656,7 @@ func addHypervisorCPUOverrides(ocispec specs.Spec, sbConfig *vc.SandboxConfig) e return fmt.Errorf("Error encountered parsing annotation default_vcpus: %v, please specify numeric value", err) } - numCPUs := goruntime.NumCPU() + numCPUs := utils.GetPhysicalCPUNumber() if uint32(vcpus) > uint32(numCPUs) { return fmt.Errorf("Number of cpus %d specified in annotation default_vcpus is greater than the number of CPUs %d on the system", vcpus, numCPUs) @@ -671,7 +671,7 @@ func addHypervisorCPUOverrides(ocispec specs.Spec, sbConfig *vc.SandboxConfig) e return fmt.Errorf("Error encountered parsing annotation for default_maxvcpus: %v, please specify positive numeric value", err) } - numCPUs := goruntime.NumCPU() + numCPUs := utils.GetPhysicalCPUNumber() max := uint32(maxVCPUs) if max > uint32(numCPUs) { diff --git a/src/runtime/virtcontainers/utils/utils.go b/src/runtime/virtcontainers/utils/utils.go index e49f55a..7023318 100644 --- a/src/runtime/virtcontainers/utils/utils.go +++ b/src/runtime/virtcontainers/utils/utils.go @@ -6,12 +6,14 @@ package utils import ( + "bufio" "crypto/rand" "errors" "fmt" "os" "os/exec" "path/filepath" + "strings" "syscall" "time" @@ -28,11 +30,26 @@ const fileMode0755 = os.FileMode(0755) // MibToBytesShift the number to shift needed to convert MiB to Bytes const MibToBytesShift = 20 +const ( + // Min needed memory size to start a Kata VM + MinMemorySizeInMB = 300 + MinMemorySizeInByte = MinMemorySizeInMB << MibToBytesShift + + // Max support memory size in the Kata VM + MaxMemorySizeInMB = 512 * 1024 + MaxMemorySizeInByte = MaxMemorySizeInMB << MibToBytesShift +) + // MaxSocketPathLen is the effective maximum Unix domain socket length. // // See unix(7). const MaxSocketPathLen = 107 +const ( + procCPUInfoPath = "/proc/cpuinfo" + processorIdentifier = "processor" +) + // VHostVSockDevicePath path to vhost-vsock device var VHostVSockDevicePath = "/dev/vhost-vsock" @@ -390,3 +407,28 @@ outer: return nil } + +// GetPhysicalCPUNumber return the number of the CPUs in the physical machine +func GetPhysicalCPUNumber() int { + f, err := os.Open(procCPUInfoPath) + if err != nil { + return 0 + } + defer f.Close() + + cpuNum := 0 + s := bufio.NewScanner(f) + for s.Scan() { + if err := s.Err(); err != nil { + return 0 + } + + fields := strings.Fields(s.Text()) + if len(fields) > 0 { + if fields[0] == processorIdentifier { + cpuNum++ + } + } + } + return cpuNum +} -- 2.25.1