summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/fs/inotify_watch.go12
-rw-r--r--pkg/sentry/strace/linux64.go2
-rw-r--r--test/syscalls/linux/inotify.cc28
3 files changed, 36 insertions, 6 deletions
diff --git a/pkg/sentry/fs/inotify_watch.go b/pkg/sentry/fs/inotify_watch.go
index b83544c9f..d33e7e498 100644
--- a/pkg/sentry/fs/inotify_watch.go
+++ b/pkg/sentry/fs/inotify_watch.go
@@ -76,15 +76,17 @@ 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 | atomic.LoadUint32(&w.mask)
- matchedEvents := effectiveMask & events
-
- if matchedEvents == 0 {
+ mask := atomic.LoadUint32(&w.mask)
+ if mask&events == 0 {
// We weren't watching for this event.
return
}
+ // Event mask should include bits matched from the watch plus all control
+ // event bits.
+ unmaskableBits := ^uint32(0) &^ linux.IN_ALL_EVENTS
+ effectiveMask := unmaskableBits | mask
+ matchedEvents := effectiveMask & events
w.owner.queueEvent(newEvent(w.wd, name, matchedEvents, cookie))
}
diff --git a/pkg/sentry/strace/linux64.go b/pkg/sentry/strace/linux64.go
index e8fb711a5..de2da9369 100644
--- a/pkg/sentry/strace/linux64.go
+++ b/pkg/sentry/strace/linux64.go
@@ -271,7 +271,7 @@ var linuxAMD64 = SyscallMap{
251: makeSyscallInfo("ioprio_set", Hex, Hex, Hex),
252: makeSyscallInfo("ioprio_get", Hex, Hex),
253: makeSyscallInfo("inotify_init"),
- 254: makeSyscallInfo("inotify_add_watch", Hex, Hex, Hex),
+ 254: makeSyscallInfo("inotify_add_watch", Hex, Path, Hex),
255: makeSyscallInfo("inotify_rm_watch", Hex, Hex),
256: makeSyscallInfo("migrate_pages", Hex, Hex, Hex, Hex),
257: makeSyscallInfo("openat", Hex, Path, OpenFlags, Mode),
diff --git a/test/syscalls/linux/inotify.cc b/test/syscalls/linux/inotify.cc
index 62fc55c72..0e361496c 100644
--- a/test/syscalls/linux/inotify.cc
+++ b/test/syscalls/linux/inotify.cc
@@ -1484,6 +1484,34 @@ TEST(Inotify, MaskAddMergesWithExistingEventMask) {
ASSERT_THAT(events, Are({Event(IN_CLOSE_WRITE, wd)}));
}
+// Test that control events bits are not considered when checking event mask.
+TEST(Inotify, ControlEvents) {
+ const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+ const FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
+
+ const int wd = ASSERT_NO_ERRNO_AND_VALUE(
+ InotifyAddWatch(fd.get(), dir.path(), IN_ACCESS));
+
+ // Check that events in the mask are dispatched and that control bits are
+ // part of the event mask.
+ std::vector<std::string> files =
+ ASSERT_NO_ERRNO_AND_VALUE(ListDir(dir.path(), false));
+ ASSERT_EQ(files.size(), 2);
+
+ const std::vector<Event> events1 =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(fd.get()));
+ ASSERT_THAT(events1, Are({Event(IN_ACCESS | IN_ISDIR, wd)}));
+
+ // Check that events not in the mask are discarded.
+ const FileDescriptor dir_fd =
+ ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY | O_DIRECTORY));
+
+ const std::vector<Event> events2 =
+ ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(fd.get()));
+ ASSERT_THAT(events2, Are({}));
+}
+
} // namespace
} // namespace testing
} // namespace gvisor