gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/control/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 control 16 17 import ( 18 "errors" 19 "fmt" 20 21 "gvisor.dev/gvisor/pkg/abi/linux" 22 "gvisor.dev/gvisor/pkg/log" 23 "gvisor.dev/gvisor/pkg/sentry/kernel" 24 "gvisor.dev/gvisor/pkg/sentry/pgalloc" 25 "gvisor.dev/gvisor/pkg/sentry/state" 26 "gvisor.dev/gvisor/pkg/sentry/watchdog" 27 "gvisor.dev/gvisor/pkg/urpc" 28 ) 29 30 // ErrInvalidFiles is returned when the urpc call to Save does not include an 31 // appropriate file payload (e.g. there is no output file!). 32 var ErrInvalidFiles = errors.New("exactly one file must be provided") 33 34 // State includes state-related functions. 35 type State struct { 36 Kernel *kernel.Kernel 37 Watchdog *watchdog.Watchdog 38 } 39 40 // SaveOpts contains options for the Save RPC call. 41 type SaveOpts struct { 42 // Key is used for state integrity check. 43 Key []byte `json:"key"` 44 45 // Metadata is the set of metadata to prepend to the state file. 46 Metadata map[string]string `json:"metadata"` 47 48 // MemoryFileSaveOpts is passed to calls to pgalloc.MemoryFile.SaveTo(). 49 MemoryFileSaveOpts pgalloc.SaveOpts 50 51 // HavePagesFile indicates whether the pages file and its corresponding 52 // metadata file is provided. 53 HavePagesFile bool `json:"have_pages_file"` 54 55 // FilePayload contains the following: 56 // 1. checkpoint state file. 57 // 2. optional checkpoint pages metadata file. 58 // 3. optional checkpoint pages file. 59 urpc.FilePayload 60 61 // Resume indicates if the sandbox process should continue running 62 // after checkpointing. 63 Resume bool 64 } 65 66 // Save saves the running system. 67 func (s *State) Save(o *SaveOpts, _ *struct{}) error { 68 wantFiles := 1 69 if o.HavePagesFile { 70 wantFiles += 2 71 } 72 if gotFiles := len(o.FilePayload.Files); gotFiles != wantFiles { 73 return fmt.Errorf("got %d files, wanted %d", gotFiles, wantFiles) 74 } 75 76 // Save to the first provided stream. 77 stateFile, err := o.ReleaseFD(0) 78 if err != nil { 79 return err 80 } 81 defer stateFile.Close() 82 saveOpts := state.SaveOpts{ 83 Destination: stateFile, 84 Key: o.Key, 85 Metadata: o.Metadata, 86 MemoryFileSaveOpts: o.MemoryFileSaveOpts, 87 Callback: func(err error) { 88 if err == nil { 89 log.Infof("Save succeeded: exiting...") 90 s.Kernel.SetSaveSuccess(false /* autosave */) 91 } else { 92 log.Warningf("Save failed: %v", err) 93 s.Kernel.SetSaveError(err) 94 } 95 if !o.Resume { 96 s.Kernel.Kill(linux.WaitStatusExit(0)) 97 } 98 }, 99 } 100 if o.HavePagesFile { 101 saveOpts.PagesMetadata, err = o.ReleaseFD(1) 102 if err != nil { 103 return err 104 } 105 defer saveOpts.PagesMetadata.Close() 106 107 saveOpts.PagesFile, err = o.ReleaseFD(2) 108 if err != nil { 109 return err 110 } 111 defer saveOpts.PagesFile.Close() 112 } 113 return saveOpts.Save(s.Kernel.SupervisorContext(), s.Kernel, s.Watchdog) 114 }