github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/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 "github.com/nicocha30/gvisor-ligolo/pkg/context" 23 "github.com/nicocha30/gvisor-ligolo/pkg/errors/linuxerr" 24 "github.com/nicocha30/gvisor-ligolo/pkg/log" 25 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/inet" 26 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/kernel" 27 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/time" 28 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/vfs" 29 "github.com/nicocha30/gvisor-ligolo/pkg/sentry/watchdog" 30 "github.com/nicocha30/gvisor-ligolo/pkg/state/statefile" 31 ) 32 33 var previousMetadata map[string]string 34 35 // ErrStateFile is returned when an error is encountered writing the statefile 36 // (which may occur during open or close calls in addition to write). 37 type ErrStateFile struct { 38 err error 39 } 40 41 // Error implements error.Error(). 42 func (e ErrStateFile) Error() string { 43 return fmt.Sprintf("statefile error: %v", e.err) 44 } 45 46 // SaveOpts contains save-related options. 47 type SaveOpts struct { 48 // Destination is the save target. 49 Destination io.Writer 50 51 // Key is used for state integrity check. 52 Key []byte 53 54 // Metadata is save metadata. 55 Metadata map[string]string 56 57 // Callback is called prior to unpause, with any save error. 58 Callback func(err error) 59 } 60 61 // Save saves the system state. 62 func (opts SaveOpts) Save(ctx context.Context, k *kernel.Kernel, w *watchdog.Watchdog) error { 63 log.Infof("Sandbox save started, pausing all tasks.") 64 k.Pause() 65 k.ReceiveTaskStates() 66 defer func() { 67 k.Unpause() 68 log.Infof("Tasks resumed after save.") 69 }() 70 71 w.Stop() 72 defer w.Start() 73 74 // Supplement the metadata. 75 if opts.Metadata == nil { 76 opts.Metadata = make(map[string]string) 77 } 78 addSaveMetadata(opts.Metadata) 79 80 // Open the statefile. 81 wc, err := statefile.NewWriter(opts.Destination, opts.Key, opts.Metadata) 82 if err != nil { 83 err = ErrStateFile{err} 84 } else { 85 // Save the kernel. 86 err = k.SaveTo(ctx, wc) 87 88 // ENOSPC is a state file error. This error can only come from 89 // writing the state file, and not from fs.FileOperations.Fsync 90 // because we wrap those in kernel.TaskSet.flushWritesToFiles. 91 if linuxerr.Equals(linuxerr.ENOSPC, err) { 92 err = ErrStateFile{err} 93 } 94 95 if closeErr := wc.Close(); err == nil && closeErr != nil { 96 err = ErrStateFile{closeErr} 97 } 98 } 99 opts.Callback(err) 100 return err 101 } 102 103 // LoadOpts contains load-related options. 104 type LoadOpts struct { 105 // Destination is the load source. 106 Source io.Reader 107 108 // Key is used for state integrity check. 109 Key []byte 110 } 111 112 // Load loads the given kernel, setting the provided platform and stack. 113 func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, timeReady chan struct{}, n inet.Stack, clocks time.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error { 114 // Open the file. 115 r, m, err := statefile.NewReader(opts.Source, opts.Key) 116 if err != nil { 117 return ErrStateFile{err} 118 } 119 120 previousMetadata = m 121 122 // Restore the Kernel object graph. 123 return k.LoadFrom(ctx, r, timeReady, n, clocks, vfsOpts) 124 }