Skip to content

Commit

Permalink
Store the container specs in the statefile for spec validation.
Browse files Browse the repository at this point in the history
- Append all the container specs to the statefile during checkpoint.
- These specs are retrieved during restore and compare/validate with the new
specs passed during the restore.

PiperOrigin-RevId: 669065871
  • Loading branch information
nybidari authored and gvisor-bot committed Sep 11, 2024
1 parent 1f4299e commit 7f1edf3
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 2 deletions.
2 changes: 2 additions & 0 deletions runsc/boot/autosave.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func getSaveOpts(l *Loader, k *kernel.Kernel, isResume bool) state.SaveOpts {

func getTargetForSaveResume(l *Loader) func(k *kernel.Kernel) {
return func(k *kernel.Kernel) {
l.addContainerSpecsToCheckpoint()
saveOpts := getSaveOpts(l, k, true /* isResume */)
// Store the state file contents in a buffer for save-resume.
// There is no need to verify the state file, we just need the
Expand All @@ -74,6 +75,7 @@ func getTargetForSaveRestore(l *Loader, files []*fd.FD) func(k *kernel.Kernel) {
var once sync.Once
return func(k *kernel.Kernel) {
once.Do(func() {
l.addContainerSpecsToCheckpoint()
saveOpts := getSaveOpts(l, k, false /* isResume */)
saveOpts.Destination = files[0]
if len(files) == 3 {
Expand Down
45 changes: 43 additions & 2 deletions runsc/boot/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package boot

import (
"encoding/json"
"errors"
"fmt"
mrand "math/rand"
Expand Down Expand Up @@ -363,8 +364,16 @@ type Args struct {
SaveFDs []*fd.FD
}

// make sure stdioFDs are always the same on initial start and on restore
const startingStdioFD = 256
const (
// startingStdioFD is the starting stdioFD number used during sandbox
// start and restore. This makes sure the stdioFDs are always the same
// on initial start and on restore.
startingStdioFD = 256

// containerSpecsKey is the key used to add and pop the container specs to the
// kernel during save/restore.
containerSpecsKey = "container_specs"
)

func getRootCredentials(spec *specs.Spec, conf *config.Config, userNs *auth.UserNamespace) *auth.Credentials {
// Create capabilities.
Expand Down Expand Up @@ -1941,3 +1950,35 @@ func (l *Loader) containerRuntimeState(cid string) ContainerRuntimeState {
// Init process has stopped, but no one has called wait on it yet.
return RuntimeStateStopped
}

// addContainerSpecsToCheckpoint adds the container specs to the kernel.
func (l *Loader) addContainerSpecsToCheckpoint() {
l.mu.Lock()
s := l.containerSpecs
l.mu.Unlock()

specsMap := make(map[string][]byte)
for k, v := range s {
data, err := json.Marshal(v)
if err != nil {
log.Warningf("json marshal error for specs %v", err)
return
}
specsMap[k] = data
}
l.k.AddStateToCheckpoint(containerSpecsKey, specsMap)
}

// popContainerSpecsFromCheckpoint pops all the container specs from the kernel.
func popContainerSpecsFromCheckpoint(k *kernel.Kernel) (map[string]*specs.Spec, error) {
specsMap := (k.PopCheckpointState(containerSpecsKey)).(map[string][]byte)
oldSpecs := make(map[string]*specs.Spec)
for k, v := range specsMap {
var s specs.Spec
if err := json.Unmarshal(v, &s); err != nil {
return nil, fmt.Errorf("json unmarshal error for specs %v", err)
}
oldSpecs[k] = &s
}
return oldSpecs, nil
}
19 changes: 19 additions & 0 deletions runsc/boot/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ func createNetworkStackForRestore(l *Loader) (*stack.Stack, inet.Stack) {
return nil, hostinet.NewStack()
}

// Validate OCI specs before restoring the containers.
func validateSpecs(oldSpecs, newSpecs map[string]*specs.Spec) error {
if len(oldSpecs) != len(newSpecs) {
return fmt.Errorf("incorrect number of specs during checkpoint and restore")
}
return nil
}

func (r *restorer) restore(l *Loader) error {
log.Infof("Starting to restore %d containers", len(r.containers))

Expand Down Expand Up @@ -226,6 +234,14 @@ func (r *restorer) restore(l *Loader) error {
return err
}

oldSpecs, err := popContainerSpecsFromCheckpoint(l.k)
if err != nil {
return err
}
if err := validateSpecs(oldSpecs, l.containerSpecs); err != nil {
return err
}

// Since we have a new kernel we also must make a new watchdog.
dogOpts := watchdog.DefaultOpts
dogOpts.TaskTimeoutAction = l.root.conf.WatchdogAction
Expand Down Expand Up @@ -328,6 +344,9 @@ func (l *Loader) save(o *control.SaveOpts) (err error) {
}
o.Metadata["container_count"] = strconv.Itoa(l.containerCount())

// Save container specs.
l.addContainerSpecsToCheckpoint()

if err := preSaveImpl(l, o); err != nil {
return err
}
Expand Down

0 comments on commit 7f1edf3

Please sign in to comment.