diff options
23 files changed, 225 insertions, 258 deletions
diff --git a/pkg/sentry/fs/fdpipe/fdpipe_state_autogen.go b/pkg/sentry/fs/fdpipe/fdpipe_state_autogen.go index 68406ce66..247aba66b 100644 --- a/pkg/sentry/fs/fdpipe/fdpipe_state_autogen.go +++ b/pkg/sentry/fs/fdpipe/fdpipe_state_autogen.go @@ -13,6 +13,7 @@ func (p *pipeOperations) StateTypeName() string { func (p *pipeOperations) StateFields() []string { return []string{ + "Queue", "flags", "opener", "readAheadBuffer", @@ -24,16 +25,18 @@ func (p *pipeOperations) StateSave(stateSinkObject state.Sink) { p.beforeSave() var flagsValue fs.FileFlags flagsValue = p.saveFlags() - stateSinkObject.SaveValue(0, flagsValue) - stateSinkObject.Save(1, &p.opener) - stateSinkObject.Save(2, &p.readAheadBuffer) + stateSinkObject.SaveValue(1, flagsValue) + stateSinkObject.Save(0, &p.Queue) + stateSinkObject.Save(2, &p.opener) + stateSinkObject.Save(3, &p.readAheadBuffer) } // +checklocksignore func (p *pipeOperations) StateLoad(stateSourceObject state.Source) { - stateSourceObject.LoadWait(1, &p.opener) - stateSourceObject.Load(2, &p.readAheadBuffer) - stateSourceObject.LoadValue(0, new(fs.FileFlags), func(y interface{}) { p.loadFlags(y.(fs.FileFlags)) }) + stateSourceObject.Load(0, &p.Queue) + stateSourceObject.LoadWait(2, &p.opener) + stateSourceObject.Load(3, &p.readAheadBuffer) + stateSourceObject.LoadValue(1, new(fs.FileFlags), func(y interface{}) { p.loadFlags(y.(fs.FileFlags)) }) stateSourceObject.AfterLoad(p.afterLoad) } diff --git a/pkg/sentry/fs/fdpipe/pipe.go b/pkg/sentry/fs/fdpipe/pipe.go index 4370cce33..d2eb03bb7 100644 --- a/pkg/sentry/fs/fdpipe/pipe.go +++ b/pkg/sentry/fs/fdpipe/pipe.go @@ -45,7 +45,8 @@ type pipeOperations struct { fsutil.FileNoIoctl `state:"nosave"` fsutil.FileNoSplice `state:"nosave"` fsutil.FileUseInodeUnstableAttr `state:"nosave"` - waiter.Queue `state:"nosave"` + + waiter.Queue // flags are the flags used to open the pipe. flags fs.FileFlags `state:".(fs.FileFlags)"` diff --git a/pkg/sentry/fs/fs_state_autogen.go b/pkg/sentry/fs/fs_state_autogen.go index 62ab34d6f..22059a271 100644 --- a/pkg/sentry/fs/fs_state_autogen.go +++ b/pkg/sentry/fs/fs_state_autogen.go @@ -833,6 +833,7 @@ func (i *Inotify) StateTypeName() string { func (i *Inotify) StateFields() []string { return []string{ "id", + "Queue", "events", "scratch", "nextWatch", @@ -846,10 +847,11 @@ func (i *Inotify) beforeSave() {} func (i *Inotify) StateSave(stateSinkObject state.Sink) { i.beforeSave() stateSinkObject.Save(0, &i.id) - stateSinkObject.Save(1, &i.events) - stateSinkObject.Save(2, &i.scratch) - stateSinkObject.Save(3, &i.nextWatch) - stateSinkObject.Save(4, &i.watches) + stateSinkObject.Save(1, &i.Queue) + stateSinkObject.Save(2, &i.events) + stateSinkObject.Save(3, &i.scratch) + stateSinkObject.Save(4, &i.nextWatch) + stateSinkObject.Save(5, &i.watches) } func (i *Inotify) afterLoad() {} @@ -857,10 +859,11 @@ func (i *Inotify) afterLoad() {} // +checklocksignore func (i *Inotify) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &i.id) - stateSourceObject.Load(1, &i.events) - stateSourceObject.Load(2, &i.scratch) - stateSourceObject.Load(3, &i.nextWatch) - stateSourceObject.Load(4, &i.watches) + stateSourceObject.Load(1, &i.Queue) + stateSourceObject.Load(2, &i.events) + stateSourceObject.Load(3, &i.scratch) + stateSourceObject.Load(4, &i.nextWatch) + stateSourceObject.Load(5, &i.watches) } func (e *Event) StateTypeName() string { diff --git a/pkg/sentry/fs/host/host_state_autogen.go b/pkg/sentry/fs/host/host_state_autogen.go index b06247919..50869fd79 100644 --- a/pkg/sentry/fs/host/host_state_autogen.go +++ b/pkg/sentry/fs/host/host_state_autogen.go @@ -115,6 +115,7 @@ func (i *inodeFileState) StateTypeName() string { func (i *inodeFileState) StateFields() []string { return []string{ "descriptor", + "queue", "sattr", "savedUAttr", } @@ -125,19 +126,18 @@ func (i *inodeFileState) beforeSave() {} // +checklocksignore func (i *inodeFileState) StateSave(stateSinkObject state.Sink) { i.beforeSave() - if !state.IsZeroValue(&i.queue) { - state.Failf("queue is %#v, expected zero", &i.queue) - } stateSinkObject.Save(0, &i.descriptor) - stateSinkObject.Save(1, &i.sattr) - stateSinkObject.Save(2, &i.savedUAttr) + stateSinkObject.Save(1, &i.queue) + stateSinkObject.Save(2, &i.sattr) + stateSinkObject.Save(3, &i.savedUAttr) } // +checklocksignore func (i *inodeFileState) StateLoad(stateSourceObject state.Source) { stateSourceObject.LoadWait(0, &i.descriptor) - stateSourceObject.LoadWait(1, &i.sattr) - stateSourceObject.Load(2, &i.savedUAttr) + stateSourceObject.Load(1, &i.queue) + stateSourceObject.LoadWait(2, &i.sattr) + stateSourceObject.Load(3, &i.savedUAttr) stateSourceObject.AfterLoad(i.afterLoad) } diff --git a/pkg/sentry/fs/host/inode.go b/pkg/sentry/fs/host/inode.go index 92d58e3e9..99c37291e 100644 --- a/pkg/sentry/fs/host/inode.go +++ b/pkg/sentry/fs/host/inode.go @@ -70,7 +70,7 @@ type inodeFileState struct { descriptor *descriptor `state:"wait"` // Event queue for blocking operations. - queue waiter.Queue `state:"zerovalue"` + queue waiter.Queue // sattr is used to restore the inodeOperations. sattr fs.StableAttr `state:"wait"` diff --git a/pkg/sentry/fs/inotify.go b/pkg/sentry/fs/inotify.go index 51cd6cd37..941f37116 100644 --- a/pkg/sentry/fs/inotify.go +++ b/pkg/sentry/fs/inotify.go @@ -43,7 +43,7 @@ type Inotify struct { // user, since we may aggressively reuse an id on S/R. id uint64 - waiter.Queue `state:"nosave"` + waiter.Queue // evMu *only* protects the events list. We need a separate lock because // while queuing events, a watch needs to lock the event queue, and using mu diff --git a/pkg/sentry/fs/lock/lock.go b/pkg/sentry/fs/lock/lock.go index 7d7a207cc..e39d340fe 100644 --- a/pkg/sentry/fs/lock/lock.go +++ b/pkg/sentry/fs/lock/lock.go @@ -132,7 +132,7 @@ type Locks struct { locks LockSet // blockedQueue is the queue of waiters that are waiting on a lock. - blockedQueue waiter.Queue `state:"zerovalue"` + blockedQueue waiter.Queue } // Blocker is the interface used for blocking locks. Passing a nil Blocker diff --git a/pkg/sentry/fs/lock/lock_state_autogen.go b/pkg/sentry/fs/lock/lock_state_autogen.go index 4a9d0a1d8..8ddb3795c 100644 --- a/pkg/sentry/fs/lock/lock_state_autogen.go +++ b/pkg/sentry/fs/lock/lock_state_autogen.go @@ -69,6 +69,7 @@ func (l *Locks) StateTypeName() string { func (l *Locks) StateFields() []string { return []string{ "locks", + "blockedQueue", } } @@ -77,10 +78,8 @@ func (l *Locks) beforeSave() {} // +checklocksignore func (l *Locks) StateSave(stateSinkObject state.Sink) { l.beforeSave() - if !state.IsZeroValue(&l.blockedQueue) { - state.Failf("blockedQueue is %#v, expected zero", &l.blockedQueue) - } stateSinkObject.Save(0, &l.locks) + stateSinkObject.Save(1, &l.blockedQueue) } func (l *Locks) afterLoad() {} @@ -88,6 +87,7 @@ func (l *Locks) afterLoad() {} // +checklocksignore func (l *Locks) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &l.locks) + stateSourceObject.Load(1, &l.blockedQueue) } func (r *LockRange) StateTypeName() string { diff --git a/pkg/sentry/fs/timerfd/timerfd.go b/pkg/sentry/fs/timerfd/timerfd.go index 1c8518d71..ca8be8683 100644 --- a/pkg/sentry/fs/timerfd/timerfd.go +++ b/pkg/sentry/fs/timerfd/timerfd.go @@ -43,7 +43,7 @@ type TimerOperations struct { fsutil.FileNoopFlush `state:"nosave"` fsutil.FileUseInodeUnstableAttr `state:"nosave"` - events waiter.Queue `state:"zerovalue"` + events waiter.Queue timer *ktime.Timer // val is the number of timer expirations since the last successful call to diff --git a/pkg/sentry/fs/timerfd/timerfd_state_autogen.go b/pkg/sentry/fs/timerfd/timerfd_state_autogen.go index 822eecdd6..6cab87796 100644 --- a/pkg/sentry/fs/timerfd/timerfd_state_autogen.go +++ b/pkg/sentry/fs/timerfd/timerfd_state_autogen.go @@ -12,6 +12,7 @@ func (t *TimerOperations) StateTypeName() string { func (t *TimerOperations) StateFields() []string { return []string{ + "events", "timer", "val", } @@ -22,19 +23,18 @@ func (t *TimerOperations) beforeSave() {} // +checklocksignore func (t *TimerOperations) StateSave(stateSinkObject state.Sink) { t.beforeSave() - if !state.IsZeroValue(&t.events) { - state.Failf("events is %#v, expected zero", &t.events) - } - stateSinkObject.Save(0, &t.timer) - stateSinkObject.Save(1, &t.val) + stateSinkObject.Save(0, &t.events) + stateSinkObject.Save(1, &t.timer) + stateSinkObject.Save(2, &t.val) } func (t *TimerOperations) afterLoad() {} // +checklocksignore func (t *TimerOperations) StateLoad(stateSourceObject state.Source) { - stateSourceObject.Load(0, &t.timer) - stateSourceObject.Load(1, &t.val) + stateSourceObject.Load(0, &t.events) + stateSourceObject.Load(1, &t.timer) + stateSourceObject.Load(2, &t.val) } func init() { diff --git a/pkg/sentry/fs/tty/line_discipline.go b/pkg/sentry/fs/tty/line_discipline.go index f9fca6d8e..f2c9e9668 100644 --- a/pkg/sentry/fs/tty/line_discipline.go +++ b/pkg/sentry/fs/tty/line_discipline.go @@ -102,10 +102,10 @@ type lineDiscipline struct { column int // masterWaiter is used to wait on the master end of the TTY. - masterWaiter waiter.Queue `state:"zerovalue"` + masterWaiter waiter.Queue // replicaWaiter is used to wait on the replica end of the TTY. - replicaWaiter waiter.Queue `state:"zerovalue"` + replicaWaiter waiter.Queue } func newLineDiscipline(termios linux.KernelTermios) *lineDiscipline { diff --git a/pkg/sentry/fs/tty/tty_state_autogen.go b/pkg/sentry/fs/tty/tty_state_autogen.go index 2fb0a8d27..1319a8d28 100644 --- a/pkg/sentry/fs/tty/tty_state_autogen.go +++ b/pkg/sentry/fs/tty/tty_state_autogen.go @@ -127,6 +127,8 @@ func (l *lineDiscipline) StateFields() []string { "outQueue", "termios", "column", + "masterWaiter", + "replicaWaiter", } } @@ -135,17 +137,13 @@ func (l *lineDiscipline) beforeSave() {} // +checklocksignore func (l *lineDiscipline) StateSave(stateSinkObject state.Sink) { l.beforeSave() - if !state.IsZeroValue(&l.masterWaiter) { - state.Failf("masterWaiter is %#v, expected zero", &l.masterWaiter) - } - if !state.IsZeroValue(&l.replicaWaiter) { - state.Failf("replicaWaiter is %#v, expected zero", &l.replicaWaiter) - } stateSinkObject.Save(0, &l.size) stateSinkObject.Save(1, &l.inQueue) stateSinkObject.Save(2, &l.outQueue) stateSinkObject.Save(3, &l.termios) stateSinkObject.Save(4, &l.column) + stateSinkObject.Save(5, &l.masterWaiter) + stateSinkObject.Save(6, &l.replicaWaiter) } func (l *lineDiscipline) afterLoad() {} @@ -157,6 +155,8 @@ func (l *lineDiscipline) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(2, &l.outQueue) stateSourceObject.Load(3, &l.termios) stateSourceObject.Load(4, &l.column) + stateSourceObject.Load(5, &l.masterWaiter) + stateSourceObject.Load(6, &l.replicaWaiter) } func (o *outputQueueTransformer) StateTypeName() string { diff --git a/pkg/sentry/kernel/epoll/epoll.go b/pkg/sentry/kernel/epoll/epoll.go index 6006c46a9..8d0a21baf 100644 --- a/pkg/sentry/kernel/epoll/epoll.go +++ b/pkg/sentry/kernel/epoll/epoll.go @@ -66,7 +66,7 @@ type pollEntry struct { file *refs.WeakRef `state:"manual"` id FileIdentifier `state:"wait"` userData [2]int32 - waiter waiter.Entry `state:"manual"` + waiter waiter.Entry mask waiter.EventMask flags EntryFlags @@ -102,7 +102,7 @@ type EventPoll struct { // Wait queue is used to notify interested parties when the event poll // object itself becomes readable or writable. - waiter.Queue `state:"zerovalue"` + waiter.Queue // files is the map of all the files currently being observed, it is // protected by mu. @@ -454,14 +454,3 @@ func (e *EventPoll) RemoveEntry(ctx context.Context, id FileIdentifier) error { return nil } - -// UnregisterEpollWaiters removes the epoll waiter objects from the waiting -// queues. This is different from Release() as the file is not dereferenced. -func (e *EventPoll) UnregisterEpollWaiters() { - e.mu.Lock() - defer e.mu.Unlock() - - for _, entry := range e.files { - entry.id.File.EventUnregister(&entry.waiter) - } -} diff --git a/pkg/sentry/kernel/epoll/epoll_state.go b/pkg/sentry/kernel/epoll/epoll_state.go index e08d6287f..135a6d72c 100644 --- a/pkg/sentry/kernel/epoll/epoll_state.go +++ b/pkg/sentry/kernel/epoll/epoll_state.go @@ -21,9 +21,7 @@ import ( // afterLoad is invoked by stateify. func (p *pollEntry) afterLoad() { - p.waiter.Callback = p p.file = refs.NewWeakRef(p.id.File, p) - p.id.File.EventRegister(&p.waiter, p.mask) } // afterLoad is invoked by stateify. diff --git a/pkg/sentry/kernel/epoll/epoll_state_autogen.go b/pkg/sentry/kernel/epoll/epoll_state_autogen.go index 44bd520ac..25fbc8f72 100644 --- a/pkg/sentry/kernel/epoll/epoll_state_autogen.go +++ b/pkg/sentry/kernel/epoll/epoll_state_autogen.go @@ -43,6 +43,7 @@ func (p *pollEntry) StateFields() []string { "pollEntryEntry", "id", "userData", + "waiter", "mask", "flags", "epoll", @@ -57,9 +58,10 @@ func (p *pollEntry) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(0, &p.pollEntryEntry) stateSinkObject.Save(1, &p.id) stateSinkObject.Save(2, &p.userData) - stateSinkObject.Save(3, &p.mask) - stateSinkObject.Save(4, &p.flags) - stateSinkObject.Save(5, &p.epoll) + stateSinkObject.Save(3, &p.waiter) + stateSinkObject.Save(4, &p.mask) + stateSinkObject.Save(5, &p.flags) + stateSinkObject.Save(6, &p.epoll) } // +checklocksignore @@ -67,9 +69,10 @@ func (p *pollEntry) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &p.pollEntryEntry) stateSourceObject.LoadWait(1, &p.id) stateSourceObject.Load(2, &p.userData) - stateSourceObject.Load(3, &p.mask) - stateSourceObject.Load(4, &p.flags) - stateSourceObject.Load(5, &p.epoll) + stateSourceObject.Load(3, &p.waiter) + stateSourceObject.Load(4, &p.mask) + stateSourceObject.Load(5, &p.flags) + stateSourceObject.Load(6, &p.epoll) stateSourceObject.AfterLoad(p.afterLoad) } @@ -79,6 +82,7 @@ func (e *EventPoll) StateTypeName() string { func (e *EventPoll) StateFields() []string { return []string{ + "Queue", "files", "readyList", "waitingList", @@ -109,21 +113,20 @@ func (e *EventPoll) StateSave(stateSinkObject state.Sink) { if !state.IsZeroValue(&e.FileNoMMap) { state.Failf("FileNoMMap is %#v, expected zero", &e.FileNoMMap) } - if !state.IsZeroValue(&e.Queue) { - state.Failf("Queue is %#v, expected zero", &e.Queue) - } - stateSinkObject.Save(0, &e.files) - stateSinkObject.Save(1, &e.readyList) - stateSinkObject.Save(2, &e.waitingList) - stateSinkObject.Save(3, &e.disabledList) + stateSinkObject.Save(0, &e.Queue) + stateSinkObject.Save(1, &e.files) + stateSinkObject.Save(2, &e.readyList) + stateSinkObject.Save(3, &e.waitingList) + stateSinkObject.Save(4, &e.disabledList) } // +checklocksignore func (e *EventPoll) StateLoad(stateSourceObject state.Source) { - stateSourceObject.Load(0, &e.files) - stateSourceObject.Load(1, &e.readyList) - stateSourceObject.Load(2, &e.waitingList) - stateSourceObject.Load(3, &e.disabledList) + stateSourceObject.Load(0, &e.Queue) + stateSourceObject.Load(1, &e.files) + stateSourceObject.Load(2, &e.readyList) + stateSourceObject.Load(3, &e.waitingList) + stateSourceObject.Load(4, &e.disabledList) stateSourceObject.AfterLoad(e.afterLoad) } diff --git a/pkg/sentry/kernel/eventfd/eventfd.go b/pkg/sentry/kernel/eventfd/eventfd.go index 5ea44a2c2..bf625dede 100644 --- a/pkg/sentry/kernel/eventfd/eventfd.go +++ b/pkg/sentry/kernel/eventfd/eventfd.go @@ -54,7 +54,7 @@ type EventOperations struct { // Queue is used to notify interested parties when the event object // becomes readable or writable. - wq waiter.Queue `state:"zerovalue"` + wq waiter.Queue // val is the current value of the event counter. val uint64 diff --git a/pkg/sentry/kernel/eventfd/eventfd_state_autogen.go b/pkg/sentry/kernel/eventfd/eventfd_state_autogen.go index 596920c42..97b5089d1 100644 --- a/pkg/sentry/kernel/eventfd/eventfd_state_autogen.go +++ b/pkg/sentry/kernel/eventfd/eventfd_state_autogen.go @@ -12,6 +12,7 @@ func (e *EventOperations) StateTypeName() string { func (e *EventOperations) StateFields() []string { return []string{ + "wq", "val", "semMode", "hostfd", @@ -23,21 +24,20 @@ func (e *EventOperations) beforeSave() {} // +checklocksignore func (e *EventOperations) StateSave(stateSinkObject state.Sink) { e.beforeSave() - if !state.IsZeroValue(&e.wq) { - state.Failf("wq is %#v, expected zero", &e.wq) - } - stateSinkObject.Save(0, &e.val) - stateSinkObject.Save(1, &e.semMode) - stateSinkObject.Save(2, &e.hostfd) + stateSinkObject.Save(0, &e.wq) + stateSinkObject.Save(1, &e.val) + stateSinkObject.Save(2, &e.semMode) + stateSinkObject.Save(3, &e.hostfd) } func (e *EventOperations) afterLoad() {} // +checklocksignore func (e *EventOperations) StateLoad(stateSourceObject state.Source) { - stateSourceObject.Load(0, &e.val) - stateSourceObject.Load(1, &e.semMode) - stateSourceObject.Load(2, &e.hostfd) + stateSourceObject.Load(0, &e.wq) + stateSourceObject.Load(1, &e.val) + stateSourceObject.Load(2, &e.semMode) + stateSourceObject.Load(3, &e.hostfd) } func init() { diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go index f913d25db..5dc821a48 100644 --- a/pkg/sentry/kernel/kernel.go +++ b/pkg/sentry/kernel/kernel.go @@ -57,7 +57,6 @@ import ( "gvisor.dev/gvisor/pkg/sentry/hostcpu" "gvisor.dev/gvisor/pkg/sentry/inet" "gvisor.dev/gvisor/pkg/sentry/kernel/auth" - "gvisor.dev/gvisor/pkg/sentry/kernel/epoll" "gvisor.dev/gvisor/pkg/sentry/kernel/futex" "gvisor.dev/gvisor/pkg/sentry/kernel/sched" ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time" @@ -486,11 +485,6 @@ func (k *Kernel) SaveTo(ctx context.Context, w wire.Writer) error { return err } - // Remove all epoll waiter objects from underlying wait queues. - // NOTE: for programs to resume execution in future snapshot scenarios, - // we will need to re-establish these waiter objects after saving. - k.tasks.unregisterEpollWaiters(ctx) - // Clear the dirent cache before saving because Dirents must be Loaded in a // particular order (parents before children), and Loading dirents from a cache // breaks that order. @@ -623,32 +617,6 @@ func (k *Kernel) flushWritesToFiles(ctx context.Context) error { }) } -// Preconditions: !VFS2Enabled. -func (ts *TaskSet) unregisterEpollWaiters(ctx context.Context) { - ts.mu.RLock() - defer ts.mu.RUnlock() - - // Tasks that belong to the same process could potentially point to the - // same FDTable. So we retain a map of processed ones to avoid - // processing the same FDTable multiple times. - processed := make(map[*FDTable]struct{}) - for t := range ts.Root.tids { - // We can skip locking Task.mu here since the kernel is paused. - if t.fdTable == nil { - continue - } - if _, ok := processed[t.fdTable]; ok { - continue - } - t.fdTable.forEach(ctx, func(_ int32, file *fs.File, _ *vfs.FileDescription, _ FDFlags) { - if e, ok := file.FileOperations.(*epoll.EventPoll); ok { - e.UnregisterEpollWaiters() - } - }) - processed[t.fdTable] = struct{}{} - } -} - // Preconditions: The kernel must be paused. func (k *Kernel) invalidateUnsavableMappings(ctx context.Context) error { invalidated := make(map[*mm.MemoryManager]struct{}) diff --git a/pkg/sentry/kernel/kernel_state_autogen.go b/pkg/sentry/kernel/kernel_state_autogen.go index d48c96425..ef8dd88f6 100644 --- a/pkg/sentry/kernel/kernel_state_autogen.go +++ b/pkg/sentry/kernel/kernel_state_autogen.go @@ -1318,6 +1318,7 @@ func (t *Task) StateFields() []string { "haveSavedSignalMask", "savedSignalMask", "signalStack", + "signalQueue", "groupStopPending", "groupStopAcknowledged", "trapStopPending", @@ -1377,15 +1378,12 @@ func (t *Task) beforeSave() {} // +checklocksignore func (t *Task) StateSave(stateSinkObject state.Sink) { t.beforeSave() - if !state.IsZeroValue(&t.signalQueue) { - state.Failf("signalQueue is %#v, expected zero", &t.signalQueue) - } var ptraceTracerValue *Task ptraceTracerValue = t.savePtraceTracer() - stateSinkObject.SaveValue(31, ptraceTracerValue) + stateSinkObject.SaveValue(32, ptraceTracerValue) var syscallFiltersValue []bpf.Program syscallFiltersValue = t.saveSyscallFilters() - stateSinkObject.SaveValue(48, syscallFiltersValue) + stateSinkObject.SaveValue(49, syscallFiltersValue) stateSinkObject.Save(0, &t.taskNode) stateSinkObject.Save(1, &t.runState) stateSinkObject.Save(2, &t.taskWorkCount) @@ -1399,55 +1397,56 @@ func (t *Task) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(10, &t.haveSavedSignalMask) stateSinkObject.Save(11, &t.savedSignalMask) stateSinkObject.Save(12, &t.signalStack) - stateSinkObject.Save(13, &t.groupStopPending) - stateSinkObject.Save(14, &t.groupStopAcknowledged) - stateSinkObject.Save(15, &t.trapStopPending) - stateSinkObject.Save(16, &t.trapNotifyPending) - stateSinkObject.Save(17, &t.stop) - stateSinkObject.Save(18, &t.exitStatus) - stateSinkObject.Save(19, &t.syscallRestartBlock) - stateSinkObject.Save(20, &t.k) - stateSinkObject.Save(21, &t.containerID) - stateSinkObject.Save(22, &t.image) - stateSinkObject.Save(23, &t.fsContext) - stateSinkObject.Save(24, &t.fdTable) - stateSinkObject.Save(25, &t.vforkParent) - stateSinkObject.Save(26, &t.exitState) - stateSinkObject.Save(27, &t.exitTracerNotified) - stateSinkObject.Save(28, &t.exitTracerAcked) - stateSinkObject.Save(29, &t.exitParentNotified) - stateSinkObject.Save(30, &t.exitParentAcked) - stateSinkObject.Save(32, &t.ptraceTracees) - stateSinkObject.Save(33, &t.ptraceSeized) - stateSinkObject.Save(34, &t.ptraceOpts) - stateSinkObject.Save(35, &t.ptraceSyscallMode) - stateSinkObject.Save(36, &t.ptraceSinglestep) - stateSinkObject.Save(37, &t.ptraceCode) - stateSinkObject.Save(38, &t.ptraceSiginfo) - stateSinkObject.Save(39, &t.ptraceEventMsg) - stateSinkObject.Save(40, &t.ptraceYAMAExceptionAdded) - stateSinkObject.Save(41, &t.ioUsage) - stateSinkObject.Save(42, &t.creds) - stateSinkObject.Save(43, &t.utsns) - stateSinkObject.Save(44, &t.ipcns) - stateSinkObject.Save(45, &t.abstractSockets) - stateSinkObject.Save(46, &t.mountNamespaceVFS2) - stateSinkObject.Save(47, &t.parentDeathSignal) - stateSinkObject.Save(49, &t.cleartid) - stateSinkObject.Save(50, &t.allowedCPUMask) - stateSinkObject.Save(51, &t.cpu) - stateSinkObject.Save(52, &t.niceness) - stateSinkObject.Save(53, &t.numaPolicy) - stateSinkObject.Save(54, &t.numaNodeMask) - stateSinkObject.Save(55, &t.netns) - stateSinkObject.Save(56, &t.rseqCPU) - stateSinkObject.Save(57, &t.oldRSeqCPUAddr) - stateSinkObject.Save(58, &t.rseqAddr) - stateSinkObject.Save(59, &t.rseqSignature) - stateSinkObject.Save(60, &t.robustList) - stateSinkObject.Save(61, &t.startTime) - stateSinkObject.Save(62, &t.kcov) - stateSinkObject.Save(63, &t.cgroups) + stateSinkObject.Save(13, &t.signalQueue) + stateSinkObject.Save(14, &t.groupStopPending) + stateSinkObject.Save(15, &t.groupStopAcknowledged) + stateSinkObject.Save(16, &t.trapStopPending) + stateSinkObject.Save(17, &t.trapNotifyPending) + stateSinkObject.Save(18, &t.stop) + stateSinkObject.Save(19, &t.exitStatus) + stateSinkObject.Save(20, &t.syscallRestartBlock) + stateSinkObject.Save(21, &t.k) + stateSinkObject.Save(22, &t.containerID) + stateSinkObject.Save(23, &t.image) + stateSinkObject.Save(24, &t.fsContext) + stateSinkObject.Save(25, &t.fdTable) + stateSinkObject.Save(26, &t.vforkParent) + stateSinkObject.Save(27, &t.exitState) + stateSinkObject.Save(28, &t.exitTracerNotified) + stateSinkObject.Save(29, &t.exitTracerAcked) + stateSinkObject.Save(30, &t.exitParentNotified) + stateSinkObject.Save(31, &t.exitParentAcked) + stateSinkObject.Save(33, &t.ptraceTracees) + stateSinkObject.Save(34, &t.ptraceSeized) + stateSinkObject.Save(35, &t.ptraceOpts) + stateSinkObject.Save(36, &t.ptraceSyscallMode) + stateSinkObject.Save(37, &t.ptraceSinglestep) + stateSinkObject.Save(38, &t.ptraceCode) + stateSinkObject.Save(39, &t.ptraceSiginfo) + stateSinkObject.Save(40, &t.ptraceEventMsg) + stateSinkObject.Save(41, &t.ptraceYAMAExceptionAdded) + stateSinkObject.Save(42, &t.ioUsage) + stateSinkObject.Save(43, &t.creds) + stateSinkObject.Save(44, &t.utsns) + stateSinkObject.Save(45, &t.ipcns) + stateSinkObject.Save(46, &t.abstractSockets) + stateSinkObject.Save(47, &t.mountNamespaceVFS2) + stateSinkObject.Save(48, &t.parentDeathSignal) + stateSinkObject.Save(50, &t.cleartid) + stateSinkObject.Save(51, &t.allowedCPUMask) + stateSinkObject.Save(52, &t.cpu) + stateSinkObject.Save(53, &t.niceness) + stateSinkObject.Save(54, &t.numaPolicy) + stateSinkObject.Save(55, &t.numaNodeMask) + stateSinkObject.Save(56, &t.netns) + stateSinkObject.Save(57, &t.rseqCPU) + stateSinkObject.Save(58, &t.oldRSeqCPUAddr) + stateSinkObject.Save(59, &t.rseqAddr) + stateSinkObject.Save(60, &t.rseqSignature) + stateSinkObject.Save(61, &t.robustList) + stateSinkObject.Save(62, &t.startTime) + stateSinkObject.Save(63, &t.kcov) + stateSinkObject.Save(64, &t.cgroups) } // +checklocksignore @@ -1465,57 +1464,58 @@ func (t *Task) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(10, &t.haveSavedSignalMask) stateSourceObject.Load(11, &t.savedSignalMask) stateSourceObject.Load(12, &t.signalStack) - stateSourceObject.Load(13, &t.groupStopPending) - stateSourceObject.Load(14, &t.groupStopAcknowledged) - stateSourceObject.Load(15, &t.trapStopPending) - stateSourceObject.Load(16, &t.trapNotifyPending) - stateSourceObject.Load(17, &t.stop) - stateSourceObject.Load(18, &t.exitStatus) - stateSourceObject.Load(19, &t.syscallRestartBlock) - stateSourceObject.Load(20, &t.k) - stateSourceObject.Load(21, &t.containerID) - stateSourceObject.Load(22, &t.image) - stateSourceObject.Load(23, &t.fsContext) - stateSourceObject.Load(24, &t.fdTable) - stateSourceObject.Load(25, &t.vforkParent) - stateSourceObject.Load(26, &t.exitState) - stateSourceObject.Load(27, &t.exitTracerNotified) - stateSourceObject.Load(28, &t.exitTracerAcked) - stateSourceObject.Load(29, &t.exitParentNotified) - stateSourceObject.Load(30, &t.exitParentAcked) - stateSourceObject.Load(32, &t.ptraceTracees) - stateSourceObject.Load(33, &t.ptraceSeized) - stateSourceObject.Load(34, &t.ptraceOpts) - stateSourceObject.Load(35, &t.ptraceSyscallMode) - stateSourceObject.Load(36, &t.ptraceSinglestep) - stateSourceObject.Load(37, &t.ptraceCode) - stateSourceObject.Load(38, &t.ptraceSiginfo) - stateSourceObject.Load(39, &t.ptraceEventMsg) - stateSourceObject.Load(40, &t.ptraceYAMAExceptionAdded) - stateSourceObject.Load(41, &t.ioUsage) - stateSourceObject.Load(42, &t.creds) - stateSourceObject.Load(43, &t.utsns) - stateSourceObject.Load(44, &t.ipcns) - stateSourceObject.Load(45, &t.abstractSockets) - stateSourceObject.Load(46, &t.mountNamespaceVFS2) - stateSourceObject.Load(47, &t.parentDeathSignal) - stateSourceObject.Load(49, &t.cleartid) - stateSourceObject.Load(50, &t.allowedCPUMask) - stateSourceObject.Load(51, &t.cpu) - stateSourceObject.Load(52, &t.niceness) - stateSourceObject.Load(53, &t.numaPolicy) - stateSourceObject.Load(54, &t.numaNodeMask) - stateSourceObject.Load(55, &t.netns) - stateSourceObject.Load(56, &t.rseqCPU) - stateSourceObject.Load(57, &t.oldRSeqCPUAddr) - stateSourceObject.Load(58, &t.rseqAddr) - stateSourceObject.Load(59, &t.rseqSignature) - stateSourceObject.Load(60, &t.robustList) - stateSourceObject.Load(61, &t.startTime) - stateSourceObject.Load(62, &t.kcov) - stateSourceObject.Load(63, &t.cgroups) - stateSourceObject.LoadValue(31, new(*Task), func(y interface{}) { t.loadPtraceTracer(y.(*Task)) }) - stateSourceObject.LoadValue(48, new([]bpf.Program), func(y interface{}) { t.loadSyscallFilters(y.([]bpf.Program)) }) + stateSourceObject.Load(13, &t.signalQueue) + stateSourceObject.Load(14, &t.groupStopPending) + stateSourceObject.Load(15, &t.groupStopAcknowledged) + stateSourceObject.Load(16, &t.trapStopPending) + stateSourceObject.Load(17, &t.trapNotifyPending) + stateSourceObject.Load(18, &t.stop) + stateSourceObject.Load(19, &t.exitStatus) + stateSourceObject.Load(20, &t.syscallRestartBlock) + stateSourceObject.Load(21, &t.k) + stateSourceObject.Load(22, &t.containerID) + stateSourceObject.Load(23, &t.image) + stateSourceObject.Load(24, &t.fsContext) + stateSourceObject.Load(25, &t.fdTable) + stateSourceObject.Load(26, &t.vforkParent) + stateSourceObject.Load(27, &t.exitState) + stateSourceObject.Load(28, &t.exitTracerNotified) + stateSourceObject.Load(29, &t.exitTracerAcked) + stateSourceObject.Load(30, &t.exitParentNotified) + stateSourceObject.Load(31, &t.exitParentAcked) + stateSourceObject.Load(33, &t.ptraceTracees) + stateSourceObject.Load(34, &t.ptraceSeized) + stateSourceObject.Load(35, &t.ptraceOpts) + stateSourceObject.Load(36, &t.ptraceSyscallMode) + stateSourceObject.Load(37, &t.ptraceSinglestep) + stateSourceObject.Load(38, &t.ptraceCode) + stateSourceObject.Load(39, &t.ptraceSiginfo) + stateSourceObject.Load(40, &t.ptraceEventMsg) + stateSourceObject.Load(41, &t.ptraceYAMAExceptionAdded) + stateSourceObject.Load(42, &t.ioUsage) + stateSourceObject.Load(43, &t.creds) + stateSourceObject.Load(44, &t.utsns) + stateSourceObject.Load(45, &t.ipcns) + stateSourceObject.Load(46, &t.abstractSockets) + stateSourceObject.Load(47, &t.mountNamespaceVFS2) + stateSourceObject.Load(48, &t.parentDeathSignal) + stateSourceObject.Load(50, &t.cleartid) + stateSourceObject.Load(51, &t.allowedCPUMask) + stateSourceObject.Load(52, &t.cpu) + stateSourceObject.Load(53, &t.niceness) + stateSourceObject.Load(54, &t.numaPolicy) + stateSourceObject.Load(55, &t.numaNodeMask) + stateSourceObject.Load(56, &t.netns) + stateSourceObject.Load(57, &t.rseqCPU) + stateSourceObject.Load(58, &t.oldRSeqCPUAddr) + stateSourceObject.Load(59, &t.rseqAddr) + stateSourceObject.Load(60, &t.rseqSignature) + stateSourceObject.Load(61, &t.robustList) + stateSourceObject.Load(62, &t.startTime) + stateSourceObject.Load(63, &t.kcov) + stateSourceObject.Load(64, &t.cgroups) + stateSourceObject.LoadValue(32, new(*Task), func(y interface{}) { t.loadPtraceTracer(y.(*Task)) }) + stateSourceObject.LoadValue(49, new([]bpf.Program), func(y interface{}) { t.loadSyscallFilters(y.([]bpf.Program)) }) stateSourceObject.AfterLoad(t.afterLoad) } @@ -2296,6 +2296,7 @@ func (t *threadGroupNode) StateTypeName() string { func (t *threadGroupNode) StateFields() []string { return []string{ "pidns", + "eventQueue", "leader", "execing", "tasks", @@ -2311,12 +2312,13 @@ func (t *threadGroupNode) beforeSave() {} func (t *threadGroupNode) StateSave(stateSinkObject state.Sink) { t.beforeSave() stateSinkObject.Save(0, &t.pidns) - stateSinkObject.Save(1, &t.leader) - stateSinkObject.Save(2, &t.execing) - stateSinkObject.Save(3, &t.tasks) - stateSinkObject.Save(4, &t.tasksCount) - stateSinkObject.Save(5, &t.liveTasks) - stateSinkObject.Save(6, &t.activeTasks) + stateSinkObject.Save(1, &t.eventQueue) + stateSinkObject.Save(2, &t.leader) + stateSinkObject.Save(3, &t.execing) + stateSinkObject.Save(4, &t.tasks) + stateSinkObject.Save(5, &t.tasksCount) + stateSinkObject.Save(6, &t.liveTasks) + stateSinkObject.Save(7, &t.activeTasks) } func (t *threadGroupNode) afterLoad() {} @@ -2324,12 +2326,13 @@ func (t *threadGroupNode) afterLoad() {} // +checklocksignore func (t *threadGroupNode) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &t.pidns) - stateSourceObject.Load(1, &t.leader) - stateSourceObject.Load(2, &t.execing) - stateSourceObject.Load(3, &t.tasks) - stateSourceObject.Load(4, &t.tasksCount) - stateSourceObject.Load(5, &t.liveTasks) - stateSourceObject.Load(6, &t.activeTasks) + stateSourceObject.Load(1, &t.eventQueue) + stateSourceObject.Load(2, &t.leader) + stateSourceObject.Load(3, &t.execing) + stateSourceObject.Load(4, &t.tasks) + stateSourceObject.Load(5, &t.tasksCount) + stateSourceObject.Load(6, &t.liveTasks) + stateSourceObject.Load(7, &t.activeTasks) } func (t *taskNode) StateTypeName() string { diff --git a/pkg/sentry/kernel/pipe/pipe.go b/pkg/sentry/kernel/pipe/pipe.go index 86beee6fe..8345473f3 100644 --- a/pkg/sentry/kernel/pipe/pipe.go +++ b/pkg/sentry/kernel/pipe/pipe.go @@ -55,7 +55,7 @@ const ( // // +stateify savable type Pipe struct { - waiter.Queue `state:"nosave"` + waiter.Queue // isNamed indicates whether this is a named pipe. // diff --git a/pkg/sentry/kernel/pipe/pipe_state_autogen.go b/pkg/sentry/kernel/pipe/pipe_state_autogen.go index 57451e951..cbacc0dd1 100644 --- a/pkg/sentry/kernel/pipe/pipe_state_autogen.go +++ b/pkg/sentry/kernel/pipe/pipe_state_autogen.go @@ -40,6 +40,7 @@ func (p *Pipe) StateTypeName() string { func (p *Pipe) StateFields() []string { return []string{ + "Queue", "isNamed", "readers", "writers", @@ -56,26 +57,28 @@ func (p *Pipe) beforeSave() {} // +checklocksignore func (p *Pipe) StateSave(stateSinkObject state.Sink) { p.beforeSave() - stateSinkObject.Save(0, &p.isNamed) - stateSinkObject.Save(1, &p.readers) - stateSinkObject.Save(2, &p.writers) - stateSinkObject.Save(3, &p.buf) - stateSinkObject.Save(4, &p.off) - stateSinkObject.Save(5, &p.size) - stateSinkObject.Save(6, &p.max) - stateSinkObject.Save(7, &p.hadWriter) + stateSinkObject.Save(0, &p.Queue) + stateSinkObject.Save(1, &p.isNamed) + stateSinkObject.Save(2, &p.readers) + stateSinkObject.Save(3, &p.writers) + stateSinkObject.Save(4, &p.buf) + stateSinkObject.Save(5, &p.off) + stateSinkObject.Save(6, &p.size) + stateSinkObject.Save(7, &p.max) + stateSinkObject.Save(8, &p.hadWriter) } // +checklocksignore func (p *Pipe) StateLoad(stateSourceObject state.Source) { - stateSourceObject.Load(0, &p.isNamed) - stateSourceObject.Load(1, &p.readers) - stateSourceObject.Load(2, &p.writers) - stateSourceObject.Load(3, &p.buf) - stateSourceObject.Load(4, &p.off) - stateSourceObject.Load(5, &p.size) - stateSourceObject.Load(6, &p.max) - stateSourceObject.Load(7, &p.hadWriter) + stateSourceObject.Load(0, &p.Queue) + stateSourceObject.Load(1, &p.isNamed) + stateSourceObject.Load(2, &p.readers) + stateSourceObject.Load(3, &p.writers) + stateSourceObject.Load(4, &p.buf) + stateSourceObject.Load(5, &p.off) + stateSourceObject.Load(6, &p.size) + stateSourceObject.Load(7, &p.max) + stateSourceObject.Load(8, &p.hadWriter) stateSourceObject.AfterLoad(p.afterLoad) } diff --git a/pkg/sentry/kernel/task.go b/pkg/sentry/kernel/task.go index b0004482c..1ea3c1bf7 100644 --- a/pkg/sentry/kernel/task.go +++ b/pkg/sentry/kernel/task.go @@ -158,7 +158,7 @@ type Task struct { // signalQueue is protected by the signalMutex. Note that the task does // not implement all queue methods, specifically the readiness checks. // The task only broadcast a notification on signal delivery. - signalQueue waiter.Queue `state:"zerovalue"` + signalQueue waiter.Queue // If groupStopPending is true, the task should participate in a group // stop in the interrupt path. diff --git a/pkg/sentry/kernel/threads.go b/pkg/sentry/kernel/threads.go index 77ad62445..e38b723ce 100644 --- a/pkg/sentry/kernel/threads.go +++ b/pkg/sentry/kernel/threads.go @@ -324,11 +324,7 @@ type threadGroupNode struct { // eventQueue is notified whenever a event of interest to Task.Wait occurs // in a child of this thread group, or a ptrace tracee of a task in this // thread group. Events are defined in task_exit.go. - // - // Note that we cannot check and save this wait queue similarly to other - // wait queues, as the queue will not be empty by the time of saving, due - // to the wait sourced from Exec(). - eventQueue waiter.Queue `state:"nosave"` + eventQueue waiter.Queue // leader is the thread group's leader, which is the oldest task in the // thread group; usually the last task in the thread group to call |