diff options
author | Rahat Mahmood <rahat@google.com> | 2018-07-03 14:07:43 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-07-03 14:08:51 -0700 |
commit | 34af9a61741f26be403231ec302b4e0795147906 (patch) | |
tree | 4906a74738e8d29dbb143db1967a37eb36534f15 /pkg | |
parent | 660f1203ff1949a7b7869b801f4aa2133d30b91f (diff) |
Fix data race on inotify.Watch.mask.
PiperOrigin-RevId: 203180463
Change-Id: Ief50988c1c028f81ec07a26e704d893e86985bf0
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/fs/inotify.go | 7 | ||||
-rw-r--r-- | pkg/sentry/fs/inotify_watch.go | 12 |
2 files changed, 11 insertions, 8 deletions
diff --git a/pkg/sentry/fs/inotify.go b/pkg/sentry/fs/inotify.go index a87be8590..6f5e8ce5e 100644 --- a/pkg/sentry/fs/inotify.go +++ b/pkg/sentry/fs/inotify.go @@ -16,6 +16,7 @@ package fs import ( "sync" + "sync/atomic" "gvisor.googlesource.com/gvisor/pkg/abi/linux" "gvisor.googlesource.com/gvisor/pkg/ilist" @@ -279,13 +280,13 @@ func (i *Inotify) AddWatch(target *Dirent, mask uint32) int32 { // same inode. Obtain an extra reference if necessary. existing.Pin(target) + newmask := mask if mergeMask := mask&linux.IN_MASK_ADD != 0; mergeMask { // "Add (OR) events to watch mask for this pathname if it already // exists (instead of replacing mask)." -- inotify(7) - existing.mask |= mask - } else { - existing.mask = mask + newmask |= atomic.LoadUint32(&existing.mask) } + atomic.StoreUint32(&existing.mask, newmask) return existing.wd } diff --git a/pkg/sentry/fs/inotify_watch.go b/pkg/sentry/fs/inotify_watch.go index ff6ec6e3e..8904ef544 100644 --- a/pkg/sentry/fs/inotify_watch.go +++ b/pkg/sentry/fs/inotify_watch.go @@ -16,6 +16,7 @@ package fs import ( "sync" + "sync/atomic" "gvisor.googlesource.com/gvisor/pkg/abi/linux" ) @@ -33,9 +34,6 @@ type Watch struct { // Descriptor for this watch. This is unique across an inotify instance. wd int32 - // Events being monitored via this watch. - mask uint32 - // The inode being watched. Note that we don't directly hold a reference on // this inode. Instead we hold a reference on the dirent(s) containing the // inode, which we record in pins. @@ -48,6 +46,10 @@ type Watch struct { // mu protects the fields below. mu sync.Mutex `state:"nosave"` + // Events being monitored via this watch. Must be accessed atomically, + // writes are protected by mu. + mask uint32 + // pins is the set of dirents this watch is currently pinning in memory by // holding a reference to them. See Pin()/Unpin(). pins map[*Dirent]bool @@ -62,7 +64,7 @@ func (w *Watch) ID() uint64 { // should continue to be be notified of events after the target has been // unlinked. func (w *Watch) NotifyParentAfterUnlink() bool { - return w.mask&linux.IN_EXCL_UNLINK == 0 + return atomic.LoadUint32(&w.mask)&linux.IN_EXCL_UNLINK == 0 } // isRenameEvent returns true if eventMask describes a rename event. @@ -73,7 +75,7 @@ func isRenameEvent(eventMask uint32) bool { // Notify queues a new event on this watch. func (w *Watch) Notify(name string, events uint32, cookie uint32) { unmaskableBits := ^uint32(0) &^ linux.IN_ALL_EVENTS - effectiveMask := unmaskableBits | w.mask + effectiveMask := unmaskableBits | atomic.LoadUint32(&w.mask) matchedEvents := effectiveMask & events if matchedEvents == 0 { |