This mode accepts the FAN_NS_MNT_* events in mask and reports these events in event->mask. Verify that FAN_REPORT_MNTID mode rejects legacy FAN_MNT_* events and verify that FAN_REPORT_MNT mode rejects FAN_NS_MNT_* events. Signed-off-by: Amir Goldstein --- .../filesystems/fanotify/mount-notify_test.c | 51 +++++++++++++++--- .../fanotify/mount-notify_test_ns.c | 54 +++++++++++++++---- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/tools/testing/selftests/filesystems/fanotify/mount-notify_test.c b/tools/testing/selftests/filesystems/fanotify/mount-notify_test.c index 6381af6a40e30..db8b355d057d4 100644 --- a/tools/testing/selftests/filesystems/fanotify/mount-notify_test.c +++ b/tools/testing/selftests/filesystems/fanotify/mount-notify_test.c @@ -42,12 +42,36 @@ FIXTURE(fanotify) { int orig_root; int ns_fd; uint64_t root_id; + uint64_t events_mask; +}; + +FIXTURE_VARIANT(fanotify) { + uint64_t events_mask; +}; + +FIXTURE_VARIANT_ADD(fanotify, mnt) { + .events_mask = FAN_MNT_ATTACH | FAN_MNT_DETACH, +}; + +FIXTURE_VARIANT_ADD(fanotify, mntid) { + .events_mask = FAN_NS_MNT_ATTACH | FAN_NS_MNT_DETACH, }; FIXTURE_SETUP(fanotify) { int i, ret; + if (variant->events_mask & FAN_EVENT_TYPE_MASK) { + int fd; + + fd = fanotify_init(FAN_REPORT_MNTID | FAN_NONBLOCK, 0); + if (fd < 0) { + ASSERT_EQ(errno, EINVAL); + SKIP(return, "FAN_REPORT_MNTID not supported"); + } + close(fd); + } + ASSERT_EQ(unshare(CLONE_NEWNS), 0); self->ns_fd = open("/proc/self/ns/mnt", O_RDONLY); @@ -74,22 +98,33 @@ FIXTURE_SETUP(fanotify) self->root_id = get_unique_mnt_id("/"); ASSERT_NE(self->root_id, 0); + uint64_t ns_event_type = FAN_NS_MNT_ATTACH & FAN_EVENT_TYPE_MASK; + + self->events_mask = variant->events_mask; + for (i = 0; i < NUM_FAN_FDS; i++) { - self->fan_fd[i] = fanotify_init(FAN_REPORT_MNT | FAN_NONBLOCK, - 0); + self->fan_fd[i] = fanotify_init(FAN_NONBLOCK | + (self->events_mask & + FAN_EVENT_TYPE_MASK ? + FAN_REPORT_MNTID : + FAN_REPORT_MNT), 0); ASSERT_GE(self->fan_fd[i], 0); ret = fanotify_mark(self->fan_fd[i], FAN_MARK_ADD | - FAN_MARK_MNTNS, - FAN_MNT_ATTACH | FAN_MNT_DETACH, + FAN_MARK_MNTNS, self->events_mask, self->ns_fd, NULL); ASSERT_EQ(ret, 0); // On fd[0] we do an extra ADD that changes nothing. // On fd[1]/fd[2] we REMOVE/FLUSH which removes the mark. ret = fanotify_mark(self->fan_fd[i], mark_cmds[i] | - FAN_MARK_MNTNS, - FAN_MNT_ATTACH | FAN_MNT_DETACH, + FAN_MARK_MNTNS, self->events_mask, self->ns_fd, NULL); ASSERT_EQ(ret, 0); + /* The other watcher type is not allowed on this group */ + ret = fanotify_mark(self->fan_fd[i], FAN_MARK_ADD | + FAN_MARK_MNTNS, + self->events_mask ^ ns_event_type, + self->ns_fd, NULL); + ASSERT_NE(ret, 0); } self->rem = 0; @@ -149,7 +184,9 @@ static uint64_t expect_notify(struct __test_metadata *const _metadata, self->rem -= thislen; self->next += thislen; - *mask = meta->mask; + ASSERT_EQ(meta->mask & FAN_EVENT_TYPE_MASK, + self->events_mask & FAN_EVENT_TYPE_MASK); + *mask = meta->mask & ~FAN_EVENT_TYPE_MASK; thislen -= sizeof(*meta); mnt = ((void *) meta) + meta->event_len - thislen; diff --git a/tools/testing/selftests/filesystems/fanotify/mount-notify_test_ns.c b/tools/testing/selftests/filesystems/fanotify/mount-notify_test_ns.c index 320ee25dc8a58..a3d38f0456377 100644 --- a/tools/testing/selftests/filesystems/fanotify/mount-notify_test_ns.c +++ b/tools/testing/selftests/filesystems/fanotify/mount-notify_test_ns.c @@ -49,12 +49,36 @@ FIXTURE(fanotify) { int orig_ns_fd; int ns_fd; uint64_t root_id; + uint64_t events_mask; +}; + +FIXTURE_VARIANT(fanotify) { + uint64_t events_mask; +}; + +FIXTURE_VARIANT_ADD(fanotify, mnt) { + .events_mask = FAN_MNT_ATTACH | FAN_MNT_DETACH, +}; + +FIXTURE_VARIANT_ADD(fanotify, mntid) { + .events_mask = FAN_NS_MNT_ATTACH | FAN_NS_MNT_DETACH, }; FIXTURE_SETUP(fanotify) { int i, ret; + if (variant->events_mask & FAN_EVENT_TYPE_MASK) { + int fd; + + fd = fanotify_init(FAN_REPORT_MNTID | FAN_NONBLOCK, 0); + if (fd < 0) { + ASSERT_EQ(errno, EINVAL); + SKIP(return, "FAN_REPORT_MNTID not supported"); + } + close(fd); + } + self->orig_ns_fd = open("/proc/self/ns/mnt", O_RDONLY); ASSERT_GE(self->orig_ns_fd, 0); @@ -83,6 +107,10 @@ FIXTURE_SETUP(fanotify) self->root_id = get_unique_mnt_id("/"); ASSERT_NE(self->root_id, 0); + uint64_t ns_event_type = FAN_NS_MNT_ATTACH & FAN_EVENT_TYPE_MASK; + + self->events_mask = variant->events_mask; + for (i = 0; i < NUM_FAN_FDS; i++) { int fan_fd = fanotify_init(FAN_REPORT_FID, 0); // Verify that watching tmpfs mounted inside userns is allowed @@ -95,28 +123,34 @@ FIXTURE_SETUP(fanotify) ASSERT_NE(ret, 0); close(fan_fd); - self->fan_fd[i] = fanotify_init(FAN_REPORT_MNT | FAN_NONBLOCK, - 0); + self->fan_fd[i] = fanotify_init(FAN_NONBLOCK | + (self->events_mask & + FAN_EVENT_TYPE_MASK ? + FAN_REPORT_MNTID : + FAN_REPORT_MNT), 0); ASSERT_GE(self->fan_fd[i], 0); // Verify that watching mntns where group was created is allowed ret = fanotify_mark(self->fan_fd[i], FAN_MARK_ADD | - FAN_MARK_MNTNS, - FAN_MNT_ATTACH | FAN_MNT_DETACH, + FAN_MARK_MNTNS, self->events_mask, self->ns_fd, NULL); ASSERT_EQ(ret, 0); // ...but watching orig mntns is not allowed ret = fanotify_mark(self->fan_fd[i], FAN_MARK_ADD | - FAN_MARK_MNTNS, - FAN_MNT_ATTACH | FAN_MNT_DETACH, + FAN_MARK_MNTNS, self->events_mask, self->orig_ns_fd, NULL); ASSERT_NE(ret, 0); // On fd[0] we do an extra ADD that changes nothing. // On fd[1]/fd[2] we REMOVE/FLUSH which removes the mark. ret = fanotify_mark(self->fan_fd[i], mark_cmds[i] | - FAN_MARK_MNTNS, - FAN_MNT_ATTACH | FAN_MNT_DETACH, + FAN_MARK_MNTNS, self->events_mask, self->ns_fd, NULL); ASSERT_EQ(ret, 0); + /* The other watcher type is not allowed on this group */ + ret = fanotify_mark(self->fan_fd[i], FAN_MARK_ADD | + FAN_MARK_MNTNS, + self->events_mask ^ ns_event_type, + self->ns_fd, NULL); + ASSERT_NE(ret, 0); } self->rem = 0; @@ -176,7 +210,9 @@ static uint64_t expect_notify(struct __test_metadata *const _metadata, self->rem -= thislen; self->next += thislen; - *mask = meta->mask; + ASSERT_EQ(meta->mask & FAN_EVENT_TYPE_MASK, + self->events_mask & FAN_EVENT_TYPE_MASK); + *mask = meta->mask & ~FAN_EVENT_TYPE_MASK; thislen -= sizeof(*meta); mnt = ((void *) meta) + meta->event_len - thislen; -- 2.55.0