summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorRahat Mahmood <rahat@google.com>2018-07-03 14:07:43 -0700
committerShentubot <shentubot@google.com>2018-07-03 14:08:51 -0700
commit34af9a61741f26be403231ec302b4e0795147906 (patch)
tree4906a74738e8d29dbb143db1967a37eb36534f15 /pkg
parent660f1203ff1949a7b7869b801f4aa2133d30b91f (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.go7
-rw-r--r--pkg/sentry/fs/inotify_watch.go12
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 {