Save runsc version in the metadata during save to compare it during restore.

PiperOrigin-RevId: 736035156
This commit is contained in:
Nayana Bidari
2025-03-12 01:02:48 -07:00
committed by gVisor bot
parent f9b1ce2f7d
commit c68fb31992
4 changed files with 17 additions and 27 deletions
+3 -3
View File
@@ -25,11 +25,11 @@ import (
"gvisor.dev/gvisor/pkg/sentry/state"
"gvisor.dev/gvisor/pkg/sentry/strace"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/runsc/version"
)
func getTargetForSaveResume(l *Loader) func(k *kernel.Kernel) {
return func(k *kernel.Kernel) {
l.addVersionToCheckpoint()
l.addContainerSpecsToCheckpoint()
// Store the state file contents in a buffer for save-resume.
// There is no need to verify the state file, we just need the
@@ -39,6 +39,7 @@ func getTargetForSaveResume(l *Loader) func(k *kernel.Kernel) {
Autosave: true,
Resume: true,
Destination: &buf,
Metadata: map[string]string{VersionKey: version.Version()},
}
saveOpts.Save(k.SupervisorContext(), k, l.watchdog)
}
@@ -52,18 +53,17 @@ func getTargetForSaveRestore(l *Loader, files []*fd.FD) func(k *kernel.Kernel) {
var once sync.Once
return func(k *kernel.Kernel) {
once.Do(func() {
l.addVersionToCheckpoint()
l.addContainerSpecsToCheckpoint()
saveOpts := state.SaveOpts{
Autosave: true,
Resume: false,
Destination: files[0],
Metadata: map[string]string{VersionKey: version.Version()},
}
if len(files) == 3 {
saveOpts.PagesMetadata = files[1]
saveOpts.PagesFile = files[2]
}
saveOpts.Save(k.SupervisorContext(), k, l.watchdog)
})
}
+7 -1
View File
@@ -42,6 +42,7 @@ import (
"gvisor.dev/gvisor/runsc/boot/procfs"
"gvisor.dev/gvisor/runsc/config"
"gvisor.dev/gvisor/runsc/specutils"
"gvisor.dev/gvisor/runsc/version"
)
const (
@@ -570,7 +571,7 @@ func (cm *containerManager) Restore(o *RestoreOpts, _ *struct{}) error {
return fmt.Errorf("reading metadata from statefile: %w", err)
}
var count int
countStr, ok := metadata["container_count"]
countStr, ok := metadata[ContainerCountKey]
if !ok {
// TODO(gvisor.dev/issue/1956): Add container count with syscall save
// trigger. For now, assume that only a single container exists if metadata
@@ -594,6 +595,11 @@ func (cm *containerManager) Restore(o *RestoreOpts, _ *struct{}) error {
return fmt.Errorf("rewinding state file: %w", err)
}
checkpointVersion := metadata[VersionKey]
currentVersion := version.Version()
if checkpointVersion != currentVersion {
return fmt.Errorf("runsc version does not match across checkpoint restore, checkpoint: %v current: %v", checkpointVersion, currentVersion)
}
return cm.restorer.restoreContainerInfo(cm.l, &cm.l.root)
}
-15
View File
@@ -84,7 +84,6 @@ import (
"gvisor.dev/gvisor/runsc/profile"
"gvisor.dev/gvisor/runsc/specutils"
"gvisor.dev/gvisor/runsc/specutils/seccomp"
"gvisor.dev/gvisor/runsc/version"
// Top-level inet providers.
"gvisor.dev/gvisor/pkg/sentry/socket/hostinet"
@@ -379,10 +378,6 @@ const (
// containerSpecsKey is the key used to add and pop the container specs to the
// kernel during save/restore.
containerSpecsKey = "container_specs"
// versionKey is the key used to add and pop runsc version to the kernel
// during save/restore.
versionKey = "runsc_version"
)
func getRootCredentials(spec *specs.Spec, conf *config.Config, userNs *auth.UserNamespace) *auth.Credentials {
@@ -2048,13 +2043,3 @@ func popContainerSpecsFromCheckpoint(k *kernel.Kernel) (map[string]*specs.Spec,
}
return oldSpecs, nil
}
// addVersionToCheckpoint adds the runsc version to the kernel.
func (l *Loader) addVersionToCheckpoint() {
l.k.AddStateToCheckpoint(versionKey, version.Version())
}
// popVersionFromCheckpoint pops the runsc version from the kernel.
func popVersionFromCheckpoint(k *kernel.Kernel) string {
return (k.PopCheckpointState(versionKey)).(string)
}
+7 -8
View File
@@ -57,6 +57,11 @@ const (
// CheckpointPagesFileName is the file within the given image-path's
// directory containing the container's MemoryFile pages.
CheckpointPagesFileName = "pages.img"
// VersionKey is the key used to save runsc version in the save metadata and compare
// it across checkpoint restore.
VersionKey = "runsc_version"
// ContainerCountKey is the key used to save number of containers in the save metadata.
ContainerCountKey = "container_count"
)
// restorer manages a restore session for a sandbox. It stores information about
@@ -239,12 +244,6 @@ func (r *restorer) restore(l *Loader) error {
return fmt.Errorf("failed to load kernel: %w", err)
}
checkpointVersion := popVersionFromCheckpoint(l.k)
currentVersion := version.Version()
if checkpointVersion != currentVersion {
return fmt.Errorf("runsc version does not match across checkpoint restore, checkpoint: %v current: %v", checkpointVersion, currentVersion)
}
oldSpecs, err := popContainerSpecsFromCheckpoint(l.k)
if err != nil {
return fmt.Errorf("failed to pop container specs from checkpoint: %w", err)
@@ -357,10 +356,10 @@ func (l *Loader) save(o *control.SaveOpts) (err error) {
if o.Metadata == nil {
o.Metadata = make(map[string]string)
}
o.Metadata["container_count"] = strconv.Itoa(l.containerCount())
o.Metadata[ContainerCountKey] = strconv.Itoa(l.containerCount())
// Save runsc version.
l.addVersionToCheckpoint()
o.Metadata[VersionKey] = version.Version()
// Save container specs.
l.addContainerSpecsToCheckpoint()