Skip to content

Commit

Permalink
Validate resources during restore.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 691072283
  • Loading branch information
nybidari authored and gvisor-bot committed Oct 29, 2024
1 parent 7b3216a commit 3f0ce44
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 1 deletion.
78 changes: 77 additions & 1 deletion runsc/boot/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,76 @@ func validateArray[T any](field, cName string, oldArr, newArr []T) error {
return nil
}

func sortCapabilities(o *specs.LinuxCapabilities) {
sort.Strings(o.Bounding)
sort.Strings(o.Effective)
sort.Strings(o.Inheritable)
sort.Strings(o.Permitted)
sort.Strings(o.Ambient)
}

func validateCapabilities(field, cName string, oldCaps, newCaps *specs.LinuxCapabilities) error {
if oldCaps == nil && newCaps == nil {
return nil
}
if oldCaps == nil || newCaps == nil {
return validateError(field, cName, oldCaps, newCaps)
}
sortCapabilities(oldCaps)
sortCapabilities(newCaps)
if !reflect.DeepEqual(oldCaps, newCaps) {
return validateError(field, cName, oldCaps, newCaps)
}
return nil
}

func copyResources(o *specs.LinuxResources) specs.LinuxResources {
var n specs.LinuxResources
n.Memory = o.Memory
n.CPU = o.CPU
n.Pids = o.Pids
n.BlockIO = o.BlockIO
n.Network = o.Network

n.Rdma = make(map[string]specs.LinuxRdma, len(o.Rdma))
for key, val := range o.Rdma {
n.Rdma[key] = val
}
n.Unified = make(map[string]string, len(o.Unified))
for key, val := range o.Unified {
n.Unified[key] = val
}
n.HugepageLimits = make([]specs.LinuxHugepageLimit, len(o.HugepageLimits))
for _, lim := range o.HugepageLimits {
newLim := specs.LinuxHugepageLimit{
Pagesize: lim.Pagesize,
Limit: lim.Limit,
}
n.HugepageLimits = append(n.HugepageLimits, newLim)
}
return n
}

func validateResources(field, cName string, oldR, newR *specs.LinuxResources) error {
if oldR == nil && newR == nil {
return nil
}
if oldR == nil || newR == nil {
return validateError(field, cName, oldR, newR)
}
before := copyResources(oldR)
after := copyResources(newR)
if err := validateArray(field, cName, before.HugepageLimits, after.HugepageLimits); err != nil {
return validateError(field, cName, oldR, newR)
}
before.HugepageLimits, after.HugepageLimits = []specs.LinuxHugepageLimit{}, []specs.LinuxHugepageLimit{}

if !reflect.DeepEqual(before, after) {
return validateError(field, cName, oldR, newR)
}
return nil
}

func validateStruct(field, cName string, oldS, newS any) error {
if !reflect.DeepEqual(oldS, newS) {
return validateError(field, cName, oldS, newS)
Expand Down Expand Up @@ -355,6 +425,9 @@ func validateSpecForContainer(oldSpec, newSpec *specs.Spec, cName string) error
if ok := slices.Equal(oldProcess.Args, newProcess.Args); !ok {
return validateError("Args", cName, oldProcess.Args, newProcess.Args)
}
if err := validateCapabilities("Capabilities", cName, oldProcess.Capabilities, newProcess.Capabilities); err != nil {
return err
}

// Validate specs.Linux.
if oldLinux.CgroupsPath != newLinux.CgroupsPath {
Expand All @@ -365,6 +438,9 @@ func validateSpecForContainer(oldSpec, newSpec *specs.Spec, cName string) error
if err := validateDevices("Devices", cName, oldLinux.Devices, newLinux.Devices); err != nil {
return err
}
if err := validateResources("Resources", cName, oldLinux.Resources, newLinux.Resources); err != nil {
return err
}
if err := validateArray("UIDMappings", cName, oldLinux.UIDMappings, newLinux.UIDMappings); err != nil {
return err
}
Expand All @@ -385,7 +461,7 @@ func validateSpecForContainer(oldSpec, newSpec *specs.Spec, cName string) error
return err
}

// TODO(b/359591006): Validate Linux.Resources and Process.Capabilities.
// TODO(b/359591006): Validate Linux.Resources.Devices.
// TODO(b/359591006): Check other remaining fields for equality.
return nil
}
Expand Down
51 changes: 51 additions & 0 deletions runsc/container/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3654,6 +3654,10 @@ func TestLookupEROFS(t *testing.T) {
}
}

func int64Ptr(v int64) *int64 {
return &v
}

func TestSpecValidation(t *testing.T) {
// TODO(b/359591006): Add more tests.
tests := []struct {
Expand Down Expand Up @@ -3792,6 +3796,53 @@ func TestSpecValidation(t *testing.T) {
},
wantErr: "",
},
{
name: "Capabilities",
mutate: func(spec, restoreSpec *specs.Spec, _, _ string) {
spec.Process = &specs.Process{
Capabilities: &specs.LinuxCapabilities{
Bounding: []string{
"CAP_NET_RAW",
"CAP_SYS_NICE",
},
},
Args: []string{"/bin/true"},
}
restoreSpec.Process = &specs.Process{
Capabilities: &specs.LinuxCapabilities{
Bounding: []string{
"CAP_NET_RAW",
},
},
Args: []string{"/bin/true"},
}
},
wantErr: "Capabilities does not match across checkpoint restore",
},
{
name: "Resources",
mutate: func(spec, restoreSpec *specs.Spec, _, _ string) {
spec.Linux = &specs.Linux{
Resources: &specs.LinuxResources{
Memory: &specs.LinuxMemory{
Limit: int64Ptr(1),
Swap: int64Ptr(2),
Reservation: int64Ptr(3),
},
},
}
restoreSpec.Linux = &specs.Linux{
Resources: &specs.LinuxResources{
Memory: &specs.LinuxMemory{
Limit: int64Ptr(1),
Swap: int64Ptr(2),
Reservation: int64Ptr(5),
},
},
}
},
wantErr: "Resources does not match across checkpoint restore",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
Expand Down

0 comments on commit 3f0ce44

Please sign in to comment.