gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/state/state.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package state provides high-level state wrappers. 16 package state 17 18 import ( 19 "fmt" 20 "io" 21 22 "gvisor.dev/gvisor/pkg/context" 23 "gvisor.dev/gvisor/pkg/errors/linuxerr" 24 "gvisor.dev/gvisor/pkg/fd" 25 "gvisor.dev/gvisor/pkg/log" 26 "gvisor.dev/gvisor/pkg/sentry/inet" 27 "gvisor.dev/gvisor/pkg/sentry/kernel" 28 "gvisor.dev/gvisor/pkg/sentry/pgalloc" 29 "gvisor.dev/gvisor/pkg/sentry/time" 30 "gvisor.dev/gvisor/pkg/sentry/vfs" 31 "gvisor.dev/gvisor/pkg/sentry/watchdog" 32 "gvisor.dev/gvisor/pkg/state/statefile" 33 ) 34 35 var previousMetadata map[string]string 36 37 // ErrStateFile is returned when an error is encountered writing the statefile 38 // (which may occur during open or close calls in addition to write). 39 type ErrStateFile struct { 40 err error 41 } 42 43 // Error implements error.Error(). 44 func (e ErrStateFile) Error() string { 45 return fmt.Sprintf("statefile error: %v", e.err) 46 } 47 48 // SaveOpts contains save-related options. 49 type SaveOpts struct { 50 // Destination is the save target. 51 Destination io.Writer 52 53 // PagesMetadata is the file into which MemoryFile metadata is stored if 54 // PagesMetadata is non-nil. Otherwise this content is stored in Destination. 55 PagesMetadata *fd.FD 56 57 // PagesFile is the file in which all MemoryFile pages are stored if 58 // PagesFile is non-nil. Otherwise this content is stored in Destination. 59 PagesFile *fd.FD 60 61 // Key is used for state integrity check. 62 Key []byte 63 64 // Metadata is save metadata. 65 Metadata map[string]string 66 67 // MemoryFileSaveOpts is passed to calls to pgalloc.MemoryFile.SaveTo(). 68 MemoryFileSaveOpts pgalloc.SaveOpts 69 70 // Callback is called prior to unpause, with any save error. 71 Callback func(err error) 72 73 // Resume indicates if the statefile is used for save-resume. 74 Resume bool 75 } 76 77 // Save saves the system state. 78 func (opts SaveOpts) Save(ctx context.Context, k *kernel.Kernel, w *watchdog.Watchdog) error { 79 log.Infof("Sandbox save started, pausing all tasks.") 80 k.Pause() 81 k.ReceiveTaskStates() 82 defer func() { 83 k.Unpause() 84 log.Infof("Tasks resumed after save.") 85 }() 86 87 w.Stop() 88 defer w.Start() 89 90 // Supplement the metadata. 91 if opts.Metadata == nil { 92 opts.Metadata = make(map[string]string) 93 } 94 addSaveMetadata(opts.Metadata) 95 96 // Open the statefile. 97 wc, err := statefile.NewWriter(opts.Destination, opts.Key, opts.Metadata) 98 if err != nil { 99 err = ErrStateFile{err} 100 } else { 101 // Save the kernel. 102 err = k.SaveTo(ctx, wc, opts.PagesMetadata, opts.PagesFile, opts.MemoryFileSaveOpts) 103 104 // ENOSPC is a state file error. This error can only come from 105 // writing the state file, and not from fs.FileOperations.Fsync 106 // because we wrap those in kernel.TaskSet.flushWritesToFiles. 107 if linuxerr.Equals(linuxerr.ENOSPC, err) { 108 err = ErrStateFile{err} 109 } 110 111 if closeErr := wc.Close(); err == nil && closeErr != nil { 112 err = ErrStateFile{closeErr} 113 } 114 } 115 opts.Callback(err) 116 return err 117 } 118 119 // LoadOpts contains load-related options. 120 type LoadOpts struct { 121 // Source is the load source. 122 Source io.Reader 123 124 // PagesMetadata is the file into which MemoryFile metadata is stored if 125 // PagesMetadata is non-nil. Otherwise this content is stored in Source. 126 PagesMetadata *fd.FD 127 128 // PagesFile is the file in which all MemoryFile pages are stored if 129 // PagesFile is non-nil. Otherwise this content is stored in Source. 130 PagesFile *fd.FD 131 132 // Key is used for state integrity check. 133 Key []byte 134 } 135 136 // Load loads the given kernel, setting the provided platform and stack. 137 func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, timeReady chan struct{}, n inet.Stack, clocks time.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error { 138 // Open the file. 139 r, m, err := statefile.NewReader(opts.Source, opts.Key) 140 if err != nil { 141 return ErrStateFile{err} 142 } 143 144 previousMetadata = m 145 146 // Restore the Kernel object graph. 147 return k.LoadFrom(ctx, r, opts.PagesMetadata, opts.PagesFile, timeReady, n, clocks, vfsOpts) 148 }