diff options
Diffstat (limited to 'pkg/sentry/kernel/fasync')
-rw-r--r-- | pkg/sentry/kernel/fasync/fasync.go | 45 | ||||
-rwxr-xr-x | pkg/sentry/kernel/fasync/fasync_state_autogen.go | 2 |
2 files changed, 37 insertions, 10 deletions
diff --git a/pkg/sentry/kernel/fasync/fasync.go b/pkg/sentry/kernel/fasync/fasync.go index bcaca58f7..6b0bb0324 100644 --- a/pkg/sentry/kernel/fasync/fasync.go +++ b/pkg/sentry/kernel/fasync/fasync.go @@ -34,9 +34,23 @@ func New() fs.FileAsync { // // +stateify savable type FileAsync struct { - mu sync.Mutex `state:"nosave"` - e waiter.Entry - requester *auth.Credentials + // e is immutable after first use (which is protected by mu below). + e waiter.Entry + + // regMu protects registeration and unregistration actions on e. + // + // regMu must be held while registration decisions are being made + // through the registration action itself. + // + // Lock ordering: regMu, mu. + regMu sync.Mutex `state:"nosave"` + + // mu protects all following fields. + // + // Lock ordering: e.mu, mu. + mu sync.Mutex `state:"nosave"` + requester *auth.Credentials + registered bool // Only one of the following is allowed to be non-nil. recipientPG *kernel.ProcessGroup @@ -47,7 +61,7 @@ type FileAsync struct { // Callback sends a signal. func (a *FileAsync) Callback(e *waiter.Entry) { a.mu.Lock() - if a.e.Callback == nil { + if !a.registered { a.mu.Unlock() return } @@ -80,14 +94,21 @@ func (a *FileAsync) Callback(e *waiter.Entry) { // // The file must not be currently registered. func (a *FileAsync) Register(w waiter.Waitable) { + a.regMu.Lock() + defer a.regMu.Unlock() a.mu.Lock() - defer a.mu.Unlock() - if a.e.Callback != nil { + if a.registered { + a.mu.Unlock() panic("registering already registered file") } - a.e.Callback = a + if a.e.Callback == nil { + a.e.Callback = a + } + a.registered = true + + a.mu.Unlock() w.EventRegister(&a.e, waiter.EventIn|waiter.EventOut|waiter.EventErr|waiter.EventHUp) } @@ -95,15 +116,19 @@ func (a *FileAsync) Register(w waiter.Waitable) { // // The file must be currently registered. func (a *FileAsync) Unregister(w waiter.Waitable) { + a.regMu.Lock() + defer a.regMu.Unlock() a.mu.Lock() - defer a.mu.Unlock() - if a.e.Callback == nil { + if !a.registered { + a.mu.Unlock() panic("unregistering unregistered file") } + a.registered = false + + a.mu.Unlock() w.EventUnregister(&a.e) - a.e.Callback = nil } // Owner returns who is currently getting signals. All return values will be diff --git a/pkg/sentry/kernel/fasync/fasync_state_autogen.go b/pkg/sentry/kernel/fasync/fasync_state_autogen.go index 0ffb3f7ad..c17daa8a1 100755 --- a/pkg/sentry/kernel/fasync/fasync_state_autogen.go +++ b/pkg/sentry/kernel/fasync/fasync_state_autogen.go @@ -11,6 +11,7 @@ func (x *FileAsync) save(m state.Map) { x.beforeSave() m.Save("e", &x.e) m.Save("requester", &x.requester) + m.Save("registered", &x.registered) m.Save("recipientPG", &x.recipientPG) m.Save("recipientTG", &x.recipientTG) m.Save("recipientT", &x.recipientT) @@ -20,6 +21,7 @@ func (x *FileAsync) afterLoad() {} func (x *FileAsync) load(m state.Map) { m.Load("e", &x.e) m.Load("requester", &x.requester) + m.Load("registered", &x.registered) m.Load("recipientPG", &x.recipientPG) m.Load("recipientTG", &x.recipientTG) m.Load("recipientT", &x.recipientT) |