All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH 0/8] fanotify tests for v5.13
@ 2021-03-18 13:11 Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 1/8] syscalls/fanotify05: Fix test output when not getting overflow Amir Goldstein
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

Hi Petr,

Following tests were used for development of the two features
queued for v5.13 (in linux-next):
- Performance improvements for events merge [1]
- Unprivileged fanotify listener [2]

All test cases of fanotify05 pass on upstream, but their runtime
on linux-next is reduced by more than half.

Only the first test case of fanotify17 pass on upstream.
The rest of the test cases as well as fanotify18 and fanotify19
tests exit with TCONF on upstream. They all pass on linux-next.

Thanks,
Amir.

[1] https://lore.kernel.org/linux-fsdevel/20210304104826.3993892-1-amir73il@gmail.com/
[2] https://lore.kernel.org/linux-fsdevel/20210304112921.3996419-1-amir73il@gmail.com/

Amir Goldstein (8):
  syscalls/fanotify05: Fix test output when not getting overflow
  syscalls/fanotify05: Verify events are received by queue order
  syscalls/fanotify05: Verify getting a single overflow event
  syscalls/fanotify05: Add a test case for unlimited queue
  syscalls/fanotify05: adjust test to tunable max_queued_events
  syscalls/fanotify: New test for fanotify user limits
  syscalls/fanotify: New test to validate unprivileged user permissions
  syscalls/fanotify: New test to validate unprivileged listener events

 runtest/syscalls                              |   3 +
 testcases/kernel/syscalls/fanotify/.gitignore |   3 +
 testcases/kernel/syscalls/fanotify/fanotify.h |   3 +
 .../kernel/syscalls/fanotify/fanotify05.c     | 147 ++++++++--
 .../kernel/syscalls/fanotify/fanotify17.c     | 266 ++++++++++++++++++
 .../kernel/syscalls/fanotify/fanotify18.c     | 198 +++++++++++++
 .../kernel/syscalls/fanotify/fanotify19.c     | 253 +++++++++++++++++
 7 files changed, 845 insertions(+), 28 deletions(-)
 create mode 100644 testcases/kernel/syscalls/fanotify/fanotify17.c
 create mode 100644 testcases/kernel/syscalls/fanotify/fanotify18.c
 create mode 100644 testcases/kernel/syscalls/fanotify/fanotify19.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 1/8] syscalls/fanotify05: Fix test output when not getting overflow
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 2/8] syscalls/fanotify05: Verify events are received by queue order Amir Goldstein
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

When test does not get an overflow event, errno for empty queue was not
tested correctly and test printed a generic error instead of the intended
message about not getting an overflow event.

Use a helper function to generate events and add info prints about the
time it takes fill up the events queue and number of read events.
---
 .../kernel/syscalls/fanotify/fanotify05.c     | 50 +++++++++++++------
 1 file changed, 34 insertions(+), 16 deletions(-)

diff --git a/testcases/kernel/syscalls/fanotify/fanotify05.c b/testcases/kernel/syscalls/fanotify/fanotify05.c
index 66ac4cbc3..6be593add 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify05.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify05.c
@@ -21,11 +21,14 @@
 #include <string.h>
 #include <sys/syscall.h>
 #include "tst_test.h"
+#include "tst_timer.h"
 
 #ifdef HAVE_SYS_FANOTIFY_H
 #include "fanotify.h"
 
 #define MOUNT_PATH "fs_mnt"
+#define FNAME_PREFIX "fname_"
+#define PATH_PREFIX MOUNT_PATH "/" FNAME_PREFIX
 
 /* Currently this is fixed in kernel... */
 #define MAX_EVENTS 16384
@@ -36,37 +39,52 @@ static int fd, fd_notify;
 
 struct fanotify_event_metadata event;
 
-void test01(void)
+static void generate_events(int num_files)
 {
+	long long elapsed_ms;
 	int i;
-	int len;
 
-	/*
-	 * generate events
-	 */
-	for (i = 0; i < MAX_EVENTS + 1; i++) {
-		sprintf(fname, MOUNT_PATH"/fname_%d", i);
+	tst_timer_start(CLOCK_MONOTONIC);
+
+	for (i = 0; i < num_files; i++) {
+		sprintf(fname, PATH_PREFIX "%d", i);
 		fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0644);
 		SAFE_CLOSE(fd);
 	}
 
+	tst_timer_stop();
+
+	elapsed_ms = tst_timer_elapsed_ms();
+
+	tst_res(TINFO, "Created %d files in %llims", i, elapsed_ms);
+}
+
+void test01(void)
+{
+	int len, nevents = 0;
+	int num_files = MAX_EVENTS + 1;
+
+	/*
+	 * Generate events on unique files so they won't be merged
+	 */
+	generate_events(num_files);
+
 	while (1) {
 		/*
 		 * get list on events
 		 */
 		len = read(fd_notify, &event, sizeof(event));
 		if (len < 0) {
-			if (errno == -EAGAIN) {
-				tst_res(TFAIL, "Overflow event not "
-					"generated!\n");
-				break;
+			if (errno != EAGAIN) {
+				tst_brk(TBROK | TERRNO,
+					"read of notification event failed");
 			}
-			tst_brk(TBROK | TERRNO,
-				"read of notification event failed");
+			tst_res(TFAIL, "Overflow event not generated!\n");
 			break;
 		}
 		if (event.fd != FAN_NOFD)
 			close(event.fd);
+		nevents++;
 
 		/*
 		 * check events
@@ -92,12 +110,12 @@ void test01(void)
 				break;
 			}
 			tst_res(TPASS,
-				"got event: mask=%llx pid=%u fd=%d",
-				(unsigned long long)event.mask,
+				"Got an overflow event: pid=%u fd=%d",
 				(unsigned)event.pid, event.fd);
-				break;
+			break;
 		}
 	}
+	tst_res(TINFO, "Got %d events", nevents);
 }
 
 static void setup(void)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 2/8] syscalls/fanotify05: Verify events are received by queue order
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 1/8] syscalls/fanotify05: Fix test output when not getting overflow Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 3/8] syscalls/fanotify05: Verify getting a single overflow event Amir Goldstein
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

When all events are generated on unique objects, re-ordering no
events are expected to be merged and therefore no event re-order
is expected. Verify that events are received in the order that
they were generated.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 .../kernel/syscalls/fanotify/fanotify05.c     | 31 ++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/testcases/kernel/syscalls/fanotify/fanotify05.c b/testcases/kernel/syscalls/fanotify/fanotify05.c
index 6be593add..1ca427caa 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify05.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify05.c
@@ -18,6 +18,8 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <errno.h>
+#include <libgen.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/syscall.h>
 #include "tst_test.h"
@@ -28,6 +30,7 @@
 
 #define MOUNT_PATH "fs_mnt"
 #define FNAME_PREFIX "fname_"
+#define FNAME_PREFIX_LEN 6
 #define PATH_PREFIX MOUNT_PATH "/" FNAME_PREFIX
 
 /* Currently this is fixed in kernel... */
@@ -35,10 +38,29 @@
 
 #define BUF_SIZE 256
 static char fname[BUF_SIZE];
+static char symlnk[BUF_SIZE];
+static char fdpath[BUF_SIZE];
 static int fd, fd_notify;
 
 struct fanotify_event_metadata event;
 
+static void event_res(struct fanotify_event_metadata *event, int i)
+{
+	int len = 0;
+	const char *filename;
+	sprintf(symlnk, "/proc/self/fd/%d", event->fd);
+	len = readlink(symlnk, fdpath, sizeof(fdpath));
+	if (len < 0)
+		len = 0;
+	fdpath[len] = 0;
+	filename = basename(fdpath);
+	if (len > FNAME_PREFIX_LEN && atoi(filename + FNAME_PREFIX_LEN) != i) {
+		tst_res(TFAIL, "Got event #%d out of order filename=%s", i, filename);
+	} else if (i == 0) {
+		tst_res(TINFO, "Got event #%d filename=%s", i, filename);
+	}
+}
+
 static void generate_events(int num_files)
 {
 	long long elapsed_ms;
@@ -82,8 +104,15 @@ void test01(void)
 			tst_res(TFAIL, "Overflow event not generated!\n");
 			break;
 		}
-		if (event.fd != FAN_NOFD)
+		if (event.fd != FAN_NOFD) {
+			/*
+			 * Verify that events generated on unique files
+			 * are received by the same order they were generated.
+			 */
+			if (nevents < num_files)
+				event_res(&event, nevents);
 			close(event.fd);
+		}
 		nevents++;
 
 		/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 3/8] syscalls/fanotify05: Verify getting a single overflow event
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 1/8] syscalls/fanotify05: Fix test output when not getting overflow Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 2/8] syscalls/fanotify05: Verify events are received by queue order Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 4/8] syscalls/fanotify05: Add a test case for unlimited queue Amir Goldstein
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

Instead of generating just one extra event, generate many events after
filling events queue. The result should remain the same - just one
overflow event is expected.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 .../kernel/syscalls/fanotify/fanotify05.c     | 26 ++++++++++++-------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/testcases/kernel/syscalls/fanotify/fanotify05.c b/testcases/kernel/syscalls/fanotify/fanotify05.c
index 1ca427caa..60bcb4774 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify05.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify05.c
@@ -61,7 +61,7 @@ static void event_res(struct fanotify_event_metadata *event, int i)
 	}
 }
 
-static void generate_events(int num_files)
+static void generate_events(int open_flags, int num_files)
 {
 	long long elapsed_ms;
 	int i;
@@ -70,7 +70,7 @@ static void generate_events(int num_files)
 
 	for (i = 0; i < num_files; i++) {
 		sprintf(fname, PATH_PREFIX "%d", i);
-		fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0644);
+		fd = SAFE_OPEN(fname, open_flags, 0644);
 		SAFE_CLOSE(fd);
 	}
 
@@ -78,18 +78,24 @@ static void generate_events(int num_files)
 
 	elapsed_ms = tst_timer_elapsed_ms();
 
-	tst_res(TINFO, "Created %d files in %llims", i, elapsed_ms);
+	tst_res(TINFO, "%s %d files in %llims",
+		(open_flags & O_CREAT) ? "Created" : "Opened", i, elapsed_ms);
 }
 
 void test01(void)
 {
-	int len, nevents = 0;
+	int len, nevents = 0, got_overflow = 0;
 	int num_files = MAX_EVENTS + 1;
 
 	/*
 	 * Generate events on unique files so they won't be merged
 	 */
-	generate_events(num_files);
+	generate_events(O_RDWR | O_CREAT, num_files);
+
+	/*
+	 * Generate more events on the same files that me be merged
+	 */
+	generate_events(O_RDONLY, num_files);
 
 	while (1) {
 		/*
@@ -101,7 +107,8 @@ void test01(void)
 				tst_brk(TBROK | TERRNO,
 					"read of notification event failed");
 			}
-			tst_res(TFAIL, "Overflow event not generated!\n");
+			if (!got_overflow)
+				tst_res(TFAIL, "Overflow event not generated!\n");
 			break;
 		}
 		if (event.fd != FAN_NOFD) {
@@ -129,10 +136,11 @@ void test01(void)
 			break;
 		}
 		if (event.mask == FAN_Q_OVERFLOW) {
-			if (event.fd != FAN_NOFD) {
+			if (got_overflow || event.fd != FAN_NOFD) {
 				tst_res(TFAIL,
-					"invalid overflow event: "
+					"%s overflow event: "
 					"mask=%llx pid=%u fd=%d",
+					got_overflow ? "unexpected" : "invalid",
 					(unsigned long long)event.mask,
 					(unsigned)event.pid,
 					event.fd);
@@ -141,7 +149,7 @@ void test01(void)
 			tst_res(TPASS,
 				"Got an overflow event: pid=%u fd=%d",
 				(unsigned)event.pid, event.fd);
-			break;
+			got_overflow = 1;
 		}
 	}
 	tst_res(TINFO, "Got %d events", nevents);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 4/8] syscalls/fanotify05: Add a test case for unlimited queue
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
                   ` (2 preceding siblings ...)
  2021-03-18 13:11 ` [LTP] [PATCH 3/8] syscalls/fanotify05: Verify getting a single overflow event Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 5/8] syscalls/fanotify05: adjust test to tunable max_queued_events Amir Goldstein
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

The existing test case verifies getting an overflow event when
events cannot fit in events queue.

Add a test case to verify that no overflow is generated when
events queue size is unlimited.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 .../kernel/syscalls/fanotify/fanotify05.c     | 41 +++++++++++++++----
 1 file changed, 33 insertions(+), 8 deletions(-)

diff --git a/testcases/kernel/syscalls/fanotify/fanotify05.c b/testcases/kernel/syscalls/fanotify/fanotify05.c
index 60bcb4774..252f5cbf5 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify05.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify05.c
@@ -36,6 +36,20 @@
 /* Currently this is fixed in kernel... */
 #define MAX_EVENTS 16384
 
+static struct tcase {
+	const char *tname;
+	unsigned int init_flags;
+} tcases[] = {
+	{
+		"Limited queue",
+		FAN_CLASS_NOTIF,
+	},
+	{
+		"Unlimited queue",
+		FAN_CLASS_NOTIF | FAN_UNLIMITED_QUEUE,
+	},
+};
+
 #define BUF_SIZE 256
 static char fname[BUF_SIZE];
 static char symlnk[BUF_SIZE];
@@ -82,10 +96,19 @@ static void generate_events(int open_flags, int num_files)
 		(open_flags & O_CREAT) ? "Created" : "Opened", i, elapsed_ms);
 }
 
-void test01(void)
+static void test_fanotify(unsigned int n)
 {
+	struct tcase *tc = &tcases[n];
 	int len, nevents = 0, got_overflow = 0;
 	int num_files = MAX_EVENTS + 1;
+	int expect_overflow = !(tc->init_flags & FAN_UNLIMITED_QUEUE);
+
+	tst_res(TINFO, "Test #%d: %s", n, tc->tname);
+
+	fd_notify = SAFE_FANOTIFY_INIT(tc->init_flags | FAN_NONBLOCK, O_RDONLY);
+
+	SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_MOUNT | FAN_MARK_ADD, FAN_OPEN,
+			   AT_FDCWD, MOUNT_PATH);
 
 	/*
 	 * Generate events on unique files so they won't be merged
@@ -108,7 +131,7 @@ void test01(void)
 					"read of notification event failed");
 			}
 			if (!got_overflow)
-				tst_res(TFAIL, "Overflow event not generated!\n");
+				tst_res(expect_overflow ? TFAIL : TPASS, "Overflow event not generated!\n");
 			break;
 		}
 		if (event.fd != FAN_NOFD) {
@@ -146,22 +169,23 @@ void test01(void)
 					event.fd);
 				break;
 			}
-			tst_res(TPASS,
+			tst_res(expect_overflow ? TPASS : TFAIL,
 				"Got an overflow event: pid=%u fd=%d",
 				(unsigned)event.pid, event.fd);
 			got_overflow = 1;
 		}
 	}
 	tst_res(TINFO, "Got %d events", nevents);
+	SAFE_CLOSE(fd_notify);
 }
 
 static void setup(void)
 {
-	fd_notify = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF | FAN_NONBLOCK,
-			O_RDONLY);
+	int fd;
 
-	SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_MOUNT | FAN_MARK_ADD, FAN_OPEN,
-			  AT_FDCWD, MOUNT_PATH);
+	/* Check for kernel fanotify support */
+	fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
+	SAFE_CLOSE(fd);
 }
 
 static void cleanup(void)
@@ -171,7 +195,8 @@ static void cleanup(void)
 }
 
 static struct tst_test test = {
-	.test_all = test01,
+	.test = test_fanotify,
+	.tcnt = ARRAY_SIZE(tcases),
 	.setup = setup,
 	.cleanup = cleanup,
 	.needs_root = 1,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 5/8] syscalls/fanotify05: adjust test to tunable max_queued_events
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
                   ` (3 preceding siblings ...)
  2021-03-18 13:11 ` [LTP] [PATCH 4/8] syscalls/fanotify05: Add a test case for unlimited queue Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 6/8] syscalls/fanotify: New test for fanotify user limits Amir Goldstein
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

Similar to test inotify05, check if there is a system tunable for
/proc/sys/fs/fanotify/max_queued_events and adjust the test according
to the system limit.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 testcases/kernel/syscalls/fanotify/fanotify05.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/testcases/kernel/syscalls/fanotify/fanotify05.c b/testcases/kernel/syscalls/fanotify/fanotify05.c
index 252f5cbf5..b7028f262 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify05.c
+++ b/testcases/kernel/syscalls/fanotify/fanotify05.c
@@ -33,8 +33,12 @@
 #define FNAME_PREFIX_LEN 6
 #define PATH_PREFIX MOUNT_PATH "/" FNAME_PREFIX
 
-/* Currently this is fixed in kernel... */
-#define MAX_EVENTS 16384
+#define SYSFS_MAX_EVENTS "/proc/sys/fs/fanotify/max_queued_events"
+
+/* In older kernels this limit is fixed in kernel */
+#define DEFAULT_MAX_EVENTS 16384
+
+static int max_events;
 
 static struct tcase {
 	const char *tname;
@@ -100,7 +104,7 @@ static void test_fanotify(unsigned int n)
 {
 	struct tcase *tc = &tcases[n];
 	int len, nevents = 0, got_overflow = 0;
-	int num_files = MAX_EVENTS + 1;
+	int num_files = max_events + 1;
 	int expect_overflow = !(tc->init_flags & FAN_UNLIMITED_QUEUE);
 
 	tst_res(TINFO, "Test #%d: %s", n, tc->tname);
@@ -186,6 +190,13 @@ static void setup(void)
 	/* Check for kernel fanotify support */
 	fd = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
 	SAFE_CLOSE(fd);
+
+	/* In older kernels this limit is fixed in kernel */
+	if (access(SYSFS_MAX_EVENTS, F_OK) && errno == ENOENT)
+		max_events = DEFAULT_MAX_EVENTS;
+	else
+		SAFE_FILE_SCANF(SYSFS_MAX_EVENTS, "%d", &max_events);
+	tst_res(TINFO, "max_queued_events=%d", max_events);
 }
 
 static void cleanup(void)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 6/8] syscalls/fanotify: New test for fanotify user limits
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
                   ` (4 preceding siblings ...)
  2021-03-18 13:11 ` [LTP] [PATCH 5/8] syscalls/fanotify05: adjust test to tunable max_queued_events Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 7/8] syscalls/fanotify: New test to validate unprivileged user permissions Amir Goldstein
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

Check that fanotify groups and marks limit are enforced correctly.
If user ns is supported, verify that global limit and per user ns
limits are both enforced.

In older kernels, the groups limit per user is hardcoded 128.
In recent kernels, the global limits can be configured via
/proc/sys/fs/fanotify/max_user_* and can be further restricted
per user ns via /proc/sys/user/max_fanotify_*.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/fanotify/.gitignore |   1 +
 testcases/kernel/syscalls/fanotify/fanotify.h |   3 +
 .../kernel/syscalls/fanotify/fanotify17.c     | 266 ++++++++++++++++++
 4 files changed, 271 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fanotify/fanotify17.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 9d4c57bb2..41f1279a2 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -590,6 +590,7 @@ fanotify13 fanotify13
 fanotify14 fanotify14
 fanotify15 fanotify15
 fanotify16 fanotify16
+fanotify17 fanotify17
 
 ioperm01 ioperm01
 ioperm02 ioperm02
diff --git a/testcases/kernel/syscalls/fanotify/.gitignore b/testcases/kernel/syscalls/fanotify/.gitignore
index e7cf224fd..20fcb3718 100644
--- a/testcases/kernel/syscalls/fanotify/.gitignore
+++ b/testcases/kernel/syscalls/fanotify/.gitignore
@@ -14,4 +14,5 @@
 /fanotify14
 /fanotify15
 /fanotify16
+/fanotify17
 /fanotify_child
diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h
index 039379961..a2be18338 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify.h
+++ b/testcases/kernel/syscalls/fanotify/fanotify.h
@@ -125,6 +125,9 @@ static inline int safe_fanotify_mark(const char *file, const int lineno,
 #define FAN_OPEN_EXEC_PERM	0x00040000
 #endif
 
+/* Flags required for unprivileged user group */
+#define FANOTIFY_REQUIRED_USER_INIT_FLAGS    (FAN_REPORT_FID)
+
 /*
  * FAN_ALL_PERM_EVENTS has been deprecated, so any new permission events
  * are not to be added to it. To cover the instance where a new permission
diff --git a/testcases/kernel/syscalls/fanotify/fanotify17.c b/testcases/kernel/syscalls/fanotify/fanotify17.c
new file mode 100644
index 000000000..ee242a441
--- /dev/null
+++ b/testcases/kernel/syscalls/fanotify/fanotify17.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2018 FUJITSU LIMITED. All rights reserved.
+ * Copyright (c) 2021 CTERA Networks.  All Rights Reserved.
+ *
+ * User ns support by: Xiao Yang <yangx.jy@cn.fujitsu.com>
+ * Forked from getxattr05.c by Amir Goldstein <amir73il@gmail.com>
+ */
+
+/*
+ * DESCRIPTION
+ *     Check that fanotify groups and marks limits are enforced correctly.
+ *     If user ns is supported, verify that global limit and per user ns
+ *     limits are both enforced.
+ *     Otherwise, we only check that global groups limit is enforced.
+ */
+#define _GNU_SOURCE
+#include "config.h"
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sched.h>
+#include <stdlib.h>
+
+#include "tst_test.h"
+#include "lapi/namespaces_constants.h"
+
+#ifdef HAVE_SYS_FANOTIFY_H
+#include "fanotify.h"
+
+#define MOUNT_PATH	"fs_mnt"
+#define TEST_FILE	MOUNT_PATH "/testfile"
+#define SELF_USERNS	"/proc/self/ns/user"
+#define MAX_USERNS	"/proc/sys/user/max_user_namespaces"
+#define UID_MAP		"/proc/self/uid_map"
+
+#define GLOBAL_MAX_GROUPS "/proc/sys/fs/fanotify/max_user_groups"
+#define GLOBAL_MAX_MARKS  "/proc/sys/fs/fanotify/max_user_marks"
+#define USERNS_MAX_GROUPS "/proc/sys/user/max_fanotify_groups"
+#define USERNS_MAX_MARKS  "/proc/sys/user/max_fanotify_marks"
+
+/*
+ * In older kernels those limits were fixed in kernel.
+ * The fanotify_init() man page documents the max groups limit is 128, but the
+ * implementation actually allows one extra group.
+ */
+#define DEFAULT_MAX_GROUPS 129
+#define DEFAULT_MAX_MARKS  8192
+
+static int orig_max_userns = -1;
+static int user_ns_supported = 1;
+static int max_groups = DEFAULT_MAX_GROUPS;
+static int max_marks = DEFAULT_MAX_MARKS;
+
+static struct tcase {
+	const char *tname;
+	unsigned int init_flags;
+	/* 0: without userns, 1: with userns */
+	int set_userns;
+	/* 0: don't map root UID in userns, 1: map root UID in userns */
+	int map_root;
+	/* 0: unlimited groups in userns */
+	int max_user_groups;
+	/* 0: unlimited marks in userns */
+	int max_user_marks;
+} tcases[] = {
+	{
+		"Global groups limit in init user ns",
+		FAN_CLASS_NOTIF,
+		0, 0, 0, 0,
+	},
+	{
+		"Global groups limit in privileged user ns",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS,
+		1, 1, 0, 0,
+	},
+	{
+		"Local groups limit in unprivileged user ns",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS,
+		1, 0, 10, 0,
+	},
+	{
+		"Local marks limit in unprivileged user ns",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS,
+		1, 0, 0, 10,
+	},
+};
+
+/* Verify that groups and marks cannot be created beyond limit */
+static void verify_user_limits(unsigned int init_flags, int groups, int marks)
+{
+	int i, fd = 0, ret = 0;
+
+	for (i = 0; i <= groups; i++) {
+		fd = fanotify_init(init_flags, O_RDONLY);
+		/*
+		 * Don't bother closing fd's, the child process will exit
+		 * and all fd's will be closed.
+		 */
+		if (fd < 0)
+			break;
+
+		ret = fanotify_mark(fd, FAN_MARK_ADD, FAN_OPEN, AT_FDCWD,
+				    TEST_FILE);
+		if (ret < 0)
+			break;
+
+	}
+	if (fd > 0 && i > groups) {
+		tst_res(TFAIL,
+			"Created %d groups and marks - "
+			"groups limit (%d) exceeded", i, groups);
+	} else if (!ret && i > marks) {
+		tst_res(TFAIL,
+			"Created %d groups and marks - "
+			"marks limit (%d) exceeded", i, marks);
+	} else if (ret < 0 && errno == ENOSPC && marks < groups) {
+		/*
+		 * ENOSPC is to be returned to the calling process when
+		 * fanotify marks limit is reached.
+		 */
+		tst_res(TPASS,
+			"Created %d marks - "
+			"below marks limit (%d)", i, marks);
+	} else if (fd < 0 && errno == EMFILE) {
+		/*
+		 * EMFILE is to be returned to the calling process when
+		 * fanotify groups limit is reached.
+		 */
+		tst_res(TPASS,
+			"Created %d groups - "
+			"below groups limit (%d)", i, groups);
+	} else if (errno == EPERM) {
+		tst_res(TCONF,
+			"unprivileged fanotify not supported by kernel?");
+	} else if (fd < 0) {
+		tst_brk(TBROK | TERRNO,
+			"fd=%d, fanotify_init(%x, O_RDONLY) failed",
+			fd, init_flags);
+	} else if (ret < 0) {
+		tst_brk(TBROK | TERRNO,
+			"ret=%d, fanotify_mark(%d, FAN_MARK_ADD, FAN_OPEN, "
+			"AT_FDCWD, '" TEST_FILE "') failed", ret, fd);
+	}
+}
+
+static void do_unshare(int map_root)
+{
+	int res;
+
+	/* unshare() should support CLONE_NEWUSER flag since Linux 3.8 */
+	res = unshare(CLONE_NEWUSER);
+	if (res == -1)
+		tst_brk(TFAIL | TERRNO, "unshare(CLONE_NEWUSER) failed");
+
+	if (map_root) {
+		/*
+		 * uid_map file should exist since Linux 3.8 because
+		 * it is available on Linux 3.5
+		 */
+		if (access(UID_MAP, F_OK))
+			tst_brk(TBROK, "file %s didn't exist", UID_MAP);
+
+		SAFE_FILE_PRINTF(UID_MAP, "%d %d %d", 0, 0, 1);
+	}
+}
+
+static void test_fanotify(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+	int groups = max_groups;
+	int marks = max_marks;
+	pid_t pid;
+
+	tst_res(TINFO, "Test #%d: %s", n, tc->tname);
+
+	if (tc->set_userns && !user_ns_supported) {
+		tst_res(TCONF, "fanotify inside user namespace is not supported");
+		return;
+	}
+
+	pid = SAFE_FORK();
+	if (!pid) {
+		if (tc->set_userns) {
+			do_unshare(tc->map_root);
+			/* Not changing global limits, only per userns limits */
+			if (tc->max_user_groups && tc->max_user_groups < groups) {
+				/* Further limit user ns groups */
+				marks = groups = tc->max_user_groups;
+				SAFE_FILE_PRINTF(USERNS_MAX_GROUPS, "%d", groups);
+			}
+			if (tc->max_user_marks && tc->max_user_marks < marks) {
+				/* Further limit user ns marks */
+				marks = tc->max_user_marks;
+				SAFE_FILE_PRINTF(USERNS_MAX_MARKS, "%d", marks);
+			}
+		}
+		verify_user_limits(tc->init_flags, groups, marks);
+		exit(0);
+	}
+
+	tst_reap_children();
+}
+
+static void setup_rlimit(unsigned int max_files)
+{
+	struct rlimit rlim;
+
+	SAFE_GETRLIMIT(RLIMIT_NOFILE, &rlim);
+	rlim.rlim_cur = max_files;
+	SAFE_SETRLIMIT(RLIMIT_NOFILE, &rlim);
+}
+
+static void setup(void)
+{
+	SAFE_TOUCH(TEST_FILE, 0666, NULL);
+	/* Check for kernel fanotify support */
+	REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, TEST_FILE);
+
+	/*
+	 * The default value of max_user_namespaces is set to 0 on some distros,
+	 * We need to change the default value to call unshare().
+	 */
+	if (access(SELF_USERNS, F_OK) != 0) {
+		user_ns_supported = 0;
+	} else if (!access(MAX_USERNS, F_OK)) {
+		SAFE_FILE_SCANF(MAX_USERNS, "%d", &orig_max_userns);
+		SAFE_FILE_PRINTF(MAX_USERNS, "%d", 10);
+	}
+
+	/*
+	 * In older kernels those limits were fixed in kernel and fanotify is
+	 * not permitted inside user ns.
+	 */
+	if (access(GLOBAL_MAX_GROUPS, F_OK) && errno == ENOENT) {
+		user_ns_supported = 0;
+	} else {
+		SAFE_FILE_SCANF(GLOBAL_MAX_GROUPS, "%d", &max_groups);
+		SAFE_FILE_SCANF(GLOBAL_MAX_MARKS, "%d", &max_marks);
+	}
+	tst_res(TINFO, "max_fanotify_groups=%d max_fanotify_marks=%d",
+		max_groups, max_marks);
+
+	/* Make sure we are not limited by nr of open files */
+	setup_rlimit(max_groups * 2);
+}
+
+static void cleanup(void)
+{
+	if (orig_max_userns != -1)
+		SAFE_FILE_PRINTF(MAX_USERNS, "%d", orig_max_userns);
+}
+
+static struct tst_test test = {
+	.test = test_fanotify,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.forks_child = 1,
+	.mount_device = 1,
+	.mntpoint = MOUNT_PATH,
+};
+#else
+	TST_TEST_TCONF("system doesn't have required fanotify support");
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 7/8] syscalls/fanotify: New test to validate unprivileged user permissions
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
                   ` (5 preceding siblings ...)
  2021-03-18 13:11 ` [LTP] [PATCH 6/8] syscalls/fanotify: New test for fanotify user limits Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-18 13:11 ` [LTP] [PATCH 8/8] syscalls/fanotify: New test to validate unprivileged listener events Amir Goldstein
  2021-03-19 13:04 ` [LTP] [PATCH 0/8] fanotify tests for v5.13 Petr Vorel
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

Defined a set of new test cases to validate the fanotify interface.
They are to ensure that the correct error values are returned upon
requesting configurations forbidden for an unprivileged user.

Signed-off-by: Matthew Bobrowski <mbobrowski@mbobrowski.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/fanotify/.gitignore |   1 +
 .../kernel/syscalls/fanotify/fanotify18.c     | 198 ++++++++++++++++++
 3 files changed, 200 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fanotify/fanotify18.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 41f1279a2..9caa3cf7a 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -591,6 +591,7 @@ fanotify14 fanotify14
 fanotify15 fanotify15
 fanotify16 fanotify16
 fanotify17 fanotify17
+fanotify18 fanotify18
 
 ioperm01 ioperm01
 ioperm02 ioperm02
diff --git a/testcases/kernel/syscalls/fanotify/.gitignore b/testcases/kernel/syscalls/fanotify/.gitignore
index 20fcb3718..175e68ca3 100644
--- a/testcases/kernel/syscalls/fanotify/.gitignore
+++ b/testcases/kernel/syscalls/fanotify/.gitignore
@@ -15,4 +15,5 @@
 /fanotify15
 /fanotify16
 /fanotify17
+/fanotify18
 /fanotify_child
diff --git a/testcases/kernel/syscalls/fanotify/fanotify18.c b/testcases/kernel/syscalls/fanotify/fanotify18.c
new file mode 100644
index 000000000..1acd23ce2
--- /dev/null
+++ b/testcases/kernel/syscalls/fanotify/fanotify18.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
+ *
+ * Started by Matthew Bobrowski <mbobrowski@mbobrowski.org>
+ *
+ * DESCRIPTION
+ *	This set of tests is to ensure that the unprivileged listener feature of
+ *	fanotify is functioning as expected. The objective this test case file
+ *	is to validate whether any forbidden flags that are passed by an
+ *	unprivileged user return the correct error result.
+ */
+#define _GNU_SOURCE
+#include "config.h"
+
+#include <pwd.h>
+#include <stdio.h>
+#include <errno.h>
+#include "tst_test.h"
+#include "fanotify.h"
+
+#if defined(HAVE_SYS_FANOTIFY_H)
+#include <sys/fanotify.h>
+
+/*
+ * This is a set of intialization flags that are not permitted to be used by an
+ * unprivileged user. Thus, if supplied, either EPERM or EINVAL should be
+ * returned to the calling process respectively.
+ */
+#define DISALLOWED_INIT_FLAGS	(FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS | \
+				 FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT | \
+				 FAN_REPORT_TID)
+
+/*
+ * This is a set of mark flags that are not permitted to be used with an
+ * unprivileged listener.
+ */
+#define DISALLOWED_MARK_FLAGS	(FAN_MARK_MOUNT | FAN_MARK_FILESYSTEM)
+
+#define MOUNT_PATH	"fs_mnt"
+#define TEST_FILE	MOUNT_PATH "/testfile"
+
+static int fd_notify;
+
+static struct test_case_t {
+	const char *name;
+	unsigned long init_flags;
+	unsigned long mark_flags;
+	unsigned long long mark_mask;
+} test_cases[] = {
+	{
+		"init_flags: missing FAN_REPORT_FID",
+		FAN_CLASS_NOTIF,
+		0, 0
+	},
+	{
+		"init_flags: FAN_CLASS_CONTENT",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_CLASS_CONTENT,
+		0, 0
+	},
+	{
+		"init_flags: FAN_CLASS_PRE_CONTENT",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_CLASS_PRE_CONTENT,
+		0, 0
+	},
+	{
+		"init_flags: FAN_UNLIMITED_QUEUE",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_UNLIMITED_QUEUE,
+		0, 0
+	},
+	{
+		"init_flags: FAN_UNLIMITED_MARKS",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_UNLIMITED_MARKS,
+		0, 0
+	},
+	{
+		"init_flags: FAN_REPORT_TID",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_REPORT_TID,
+		0, 0
+	},
+	{
+		"init_flags: FAN_CLASS_NOTIF, "
+		"mark_flags: FAN_MARK_ADD | FAN_MARK_MOUNT",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_CLASS_NOTIF,
+		FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_ALL_EVENTS
+	},
+	{
+		"init_flags: FAN_CLASS_NOTIF, "
+		"mark_flags: FAN_MARK_ADD | FAN_MARK_FILESYSTEM",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_CLASS_NOTIF,
+		FAN_MARK_ADD | FAN_MARK_FILESYSTEM, FAN_ALL_EVENTS
+	},
+	{
+		"init_flags: FAN_CLASS_NOTIF, "
+		"mark_flags: FAN_MARK_ADD, "
+		"mark_mask: FAN_ALL_EVENTS",
+		FANOTIFY_REQUIRED_USER_INIT_FLAGS | FAN_CLASS_NOTIF,
+		FAN_MARK_ADD, FAN_ALL_EVENTS
+	}
+};
+
+static void test_fanotify(unsigned int n)
+{
+	struct test_case_t *tc = &test_cases[n];
+
+	tst_res(TINFO, "Test #%d %s", n, tc->name);
+
+	/* Initialize fanotify */
+	fd_notify = fanotify_init(tc->init_flags, O_RDONLY);
+
+	if (fd_notify < 0) {
+		if (errno == EPERM &&
+		    ((tc->init_flags & DISALLOWED_INIT_FLAGS) ||
+		     (tc->init_flags & FANOTIFY_REQUIRED_USER_INIT_FLAGS) !=
+		      FANOTIFY_REQUIRED_USER_INIT_FLAGS)) {
+			tst_res(TPASS,
+				"Received result EPERM, as expected");
+			return;
+		} else {
+			tst_brk(TBROK | TERRNO,
+				"fanotify_init(0x%lx, O_RDONLY) failed",
+				tc->init_flags);
+		}
+	}
+
+	/* Attempt to place mark on object */
+	if (fanotify_mark(fd_notify, tc->mark_flags, tc->mark_mask, AT_FDCWD,
+				TEST_FILE) < 0) {
+		/*
+		 * Unprivileged users are only allowed to mark inodes and not
+		 * permitted to use access permissions
+		 */
+		if (errno == EPERM &&
+			(tc->mark_flags & DISALLOWED_MARK_FLAGS ||
+			 tc->mark_mask & FAN_ALL_PERM_EVENTS)) {
+			tst_res(TPASS, "Received result EPERM, as expected");
+			return;
+		}
+
+		tst_brk(TBROK | TERRNO,
+			"fanotify_mark(%d, %lx, %llx, AT_FDCWD, %s) "
+			"failed",
+			fd_notify,
+			tc->mark_flags,
+			tc->mark_mask,
+			TEST_FILE);
+	}
+
+	tst_res(TPASS,
+		"fanotify_init() and fanotify_mark() returned successfully, "
+		"as expected");
+}
+
+static void setup(void)
+{
+	int fd;
+
+	SAFE_TOUCH(TEST_FILE, 0666, NULL);
+
+	/* Check for kernel fanotify support */
+	REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, TEST_FILE);
+
+	/* Relinquish privileged user */
+	if (geteuid() == 0) {
+		tst_res(TINFO,
+			"Running as privileged user, revoking permissions.");
+		struct passwd *nobody = SAFE_GETPWNAM("nobody");
+		SAFE_SETUID(nobody->pw_uid);
+	}
+
+	/* Check for unprivileged fanotify support */
+	fd = fanotify_init(FANOTIFY_REQUIRED_USER_INIT_FLAGS, O_RDONLY);
+	if (fd < 0) {
+		tst_brk(TCONF,
+			"unprivileged fanotify not supported by kernel?");
+	}
+	SAFE_CLOSE(fd);
+}
+
+static void cleanup(void)
+{
+	if (fd_notify > 0)
+		SAFE_CLOSE(fd_notify);
+}
+
+static struct tst_test test = {
+	.test = test_fanotify,
+	.tcnt = ARRAY_SIZE(test_cases),
+	.setup = setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.mount_device = 1,
+	.mntpoint = MOUNT_PATH,
+};
+
+#else
+	TST_TEST_CONF("System does not have required fanotify support");
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 8/8] syscalls/fanotify: New test to validate unprivileged listener events
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
                   ` (6 preceding siblings ...)
  2021-03-18 13:11 ` [LTP] [PATCH 7/8] syscalls/fanotify: New test to validate unprivileged user permissions Amir Goldstein
@ 2021-03-18 13:11 ` Amir Goldstein
  2021-03-19 13:04 ` [LTP] [PATCH 0/8] fanotify tests for v5.13 Petr Vorel
  8 siblings, 0 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-18 13:11 UTC (permalink / raw)
  To: ltp

Defined test cases that are responsible for validating that the events
returned to an unprivileged event listener contain the correct values.

Signed-off-by: Matthew Bobrowski <mbobrowski@mbobrowski.org>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 runtest/syscalls                              |   1 +
 testcases/kernel/syscalls/fanotify/.gitignore |   1 +
 .../kernel/syscalls/fanotify/fanotify19.c     | 253 ++++++++++++++++++
 3 files changed, 255 insertions(+)
 create mode 100644 testcases/kernel/syscalls/fanotify/fanotify19.c

diff --git a/runtest/syscalls b/runtest/syscalls
index 9caa3cf7a..2d1e7b648 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -592,6 +592,7 @@ fanotify15 fanotify15
 fanotify16 fanotify16
 fanotify17 fanotify17
 fanotify18 fanotify18
+fanotify19 fanotify19
 
 ioperm01 ioperm01
 ioperm02 ioperm02
diff --git a/testcases/kernel/syscalls/fanotify/.gitignore b/testcases/kernel/syscalls/fanotify/.gitignore
index 175e68ca3..9554b16b1 100644
--- a/testcases/kernel/syscalls/fanotify/.gitignore
+++ b/testcases/kernel/syscalls/fanotify/.gitignore
@@ -16,4 +16,5 @@
 /fanotify16
 /fanotify17
 /fanotify18
+/fanotify19
 /fanotify_child
diff --git a/testcases/kernel/syscalls/fanotify/fanotify19.c b/testcases/kernel/syscalls/fanotify/fanotify19.c
new file mode 100644
index 000000000..83a9aaa98
--- /dev/null
+++ b/testcases/kernel/syscalls/fanotify/fanotify19.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
+ *
+ * Started by Matthew Bobrowski <mbobrowski@mbobrowski.org>
+ *
+ * DESCRIPTION
+ *	This set of tests is to ensure that the unprivileged listener feature of
+ *	fanotify is functioning as expected. The objective of this test file is
+ *	to generate a sequence of events and ensure that the returned events
+ *	contain the limited values that an unprivileged listener is expected
+ *	to receive.
+ */
+#define _GNU_SOURCE
+#include "config.h"
+
+#include <pwd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "fanotify.h"
+
+#if defined(HAVE_SYS_FANOTIFY_H)
+#include <sys/fanotify.h>
+
+#define EVENT_MAX 1024
+#define EVENT_SIZE (sizeof (struct fanotify_event_metadata))
+#define EVENT_BUF_LEN (EVENT_MAX * EVENT_SIZE)
+#define EVENT_SET_MAX 48
+
+#define BUF_SIZE 256
+
+#define MOUNT_PATH	"fs_mnt"
+#define TEST_FILE	MOUNT_PATH "/testfile"
+
+static int fd_notify;
+static char buf[BUF_SIZE];
+static struct fanotify_event_metadata event_buf[EVENT_BUF_LEN];
+
+static struct test_case_t {
+	const char *name;
+	unsigned int fork;
+	unsigned int event_count;
+	unsigned long long event_set[EVENT_SET_MAX];
+} test_cases[] = {
+	{
+		"unprivileged listener - events by self",
+		0,
+		4,
+		{
+			FAN_OPEN,
+			FAN_ACCESS,
+			FAN_MODIFY,
+			FAN_CLOSE,
+		}
+	},
+	{
+		"unprivileged lisneter - events by child",
+		1,
+		4,
+		{
+			FAN_OPEN,
+			FAN_ACCESS,
+			FAN_MODIFY,
+			FAN_CLOSE,
+		}
+	}
+};
+
+static void generate_events(void)
+{
+	int fd;
+
+	/* FAN_OPEN */
+	fd = SAFE_OPEN(TEST_FILE, O_RDWR);
+
+	/* FAN_ACCESS */
+	SAFE_READ(0, fd, buf, BUF_SIZE);
+
+	/* FAN_MODIFY */
+	SAFE_WRITE(1, fd, TEST_FILE, 1);
+
+	/* FAN_CLOSE */
+	SAFE_CLOSE(fd);
+}
+
+static void do_fork(void)
+{
+	int status;
+	pid_t child;
+
+	child = SAFE_FORK();
+
+	if (child == 0) {
+		SAFE_CLOSE(fd_notify);
+		generate_events();
+		exit(0);
+	}
+
+	SAFE_WAITPID(child, &status, 0);
+
+	if (WIFEXITED(child) && WEXITSTATUS(child) != 0)
+		tst_brk(TBROK, "Child process terminated incorrectly. Aborting");
+}
+
+static void test_fanotify(unsigned int n)
+{
+	int len = 0;
+	pid_t pid = getpid();
+	unsigned int test_number = 0;
+	struct fanotify_event_metadata *event;
+	struct test_case_t *tc = &test_cases[n];
+
+	tst_res(TINFO, "Test #%d %s", n, tc->name);
+
+	/* Initialize fanotify */
+	fd_notify = fanotify_init(FANOTIFY_REQUIRED_USER_INIT_FLAGS, O_RDONLY);
+
+	if (fd_notify < 0) {
+		if (errno == EPERM || errno == EINVAL) {
+			tst_res(TCONF,
+				"unprivileged fanotify not supported by kernel?");
+			return;
+		} else {
+			tst_brk(TBROK | TERRNO,
+				"fanotify_init(FAN_CLASS_NOTIF, O_RDONLY) failed");
+		}
+	}
+
+	/* Place mark on object */
+	if (fanotify_mark(fd_notify, FAN_MARK_ADD, FAN_ALL_EVENTS,
+				AT_FDCWD, TEST_FILE) < 0) {
+		tst_brk(TBROK | TERRNO,
+			"fanotify_mark(%d, FAN_MARK_ADD, %d, "
+			"AT_FDCWD, %s) failed",
+			fd_notify,
+			FAN_ALL_EVENTS,
+			TEST_FILE);
+	}
+
+	/* Generate events in either child or listening process */
+	if (tc->fork)
+		do_fork();
+	else
+		generate_events();
+
+	/* Read events from queue */
+	len = SAFE_READ(0, fd_notify, event_buf + len, EVENT_BUF_LEN - len);
+
+	event = event_buf;
+
+	/* Iterate over and validate events against expected result set */
+	while (FAN_EVENT_OK(event, len) && test_number < tc->event_count) {
+		if (!(event->mask & tc->event_set[test_number])) {
+			tst_res(TFAIL,
+				"Received unexpected event mask: mask=%llx "
+				"pid=%u fd=%d",
+				(unsigned long long) event->mask,
+				(unsigned) event->pid,
+				event->fd);
+		} else if ((!tc->fork && event->pid != pid) ||
+			   (tc->fork && event->pid != 0)) {
+			tst_res(TFAIL,
+				"Received unexpected pid in event: "
+				"mask=%llx pid=%u (expected %u) fd=%d",
+				(unsigned long long) event->mask,
+				(unsigned) event->pid,
+				(tc->fork ? 0 : pid),
+				event->fd);
+		} else if (event->fd != FAN_NOFD) {
+			tst_res(TFAIL,
+				"Received unexpected file descriptor: "
+				"mask=%llx pid=%u fd=%d (expected %d)",
+				(unsigned long long) event->pid,
+				(unsigned) event->pid,
+				event->fd,
+				FAN_NOFD);
+			SAFE_CLOSE(event->fd);
+		} else {
+			tst_res(TPASS,
+				"Received event: mask=%llx, pid=%u fd=%d",
+				(unsigned long long) event->mask,
+				(unsigned) event->pid,
+				event->fd);
+		}
+
+		/* Non-permission events can be merged into a single event. */
+		event->mask &= ~tc->event_set[test_number];
+
+		if (event->mask == 0)
+			event = FAN_EVENT_NEXT(event, len);
+		test_number++;
+	}
+
+	/*
+	 * Determine whether there is still unprocessed events remaining in the
+	 * buffer. This is to cover the basis whereby the event processing loop
+	 * terminates prematurely. In that case, we need to ensure that any
+	 * event file descriptor that is open is closed so that the temporary
+	 * filesystem can be unmounted.
+	 */
+	if (FAN_EVENT_OK(event, len)) {
+		tst_res(TFAIL,
+			"Event processing loop exited prematurely. Did NOT "
+			"finish processing events in buffer. Cleaning up.");
+		while (FAN_EVENT_OK(event, len)) {
+			if (event->fd != FAN_NOFD)
+				SAFE_CLOSE(event->fd);
+			event = FAN_EVENT_NEXT(event, len);
+		}
+	}
+}
+
+static void setup(void)
+{
+	SAFE_FILE_PRINTF(TEST_FILE, "1");
+	SAFE_CHMOD(TEST_FILE, 0666);
+
+	/* Check for kernel fanotify support */
+	REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_FID, TEST_FILE);
+
+	/* Relinquish privileged user */
+	if (geteuid() == 0) {
+		tst_res(TINFO,
+			"Running as privileged user, revoking.");
+		struct passwd *nobody = SAFE_GETPWNAM("nobody");
+		SAFE_SETUID(nobody->pw_uid);
+	}
+}
+
+static void cleanup(void)
+{
+	if (fd_notify > 0)
+		SAFE_CLOSE(fd_notify);
+}
+
+static struct tst_test test = {
+	.test = test_fanotify,
+	.tcnt = ARRAY_SIZE(test_cases),
+	.setup = setup,
+	.cleanup = cleanup,
+	.forks_child = 1,
+	.needs_root = 1,
+	.mount_device = 1,
+	.mntpoint = MOUNT_PATH,
+};
+
+#else
+	TST_TEST_CONF("System does not have required fanotify support");
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 0/8] fanotify tests for v5.13
  2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
                   ` (7 preceding siblings ...)
  2021-03-18 13:11 ` [LTP] [PATCH 8/8] syscalls/fanotify: New test to validate unprivileged listener events Amir Goldstein
@ 2021-03-19 13:04 ` Petr Vorel
  2021-03-19 13:54   ` Amir Goldstein
  8 siblings, 1 reply; 15+ messages in thread
From: Petr Vorel @ 2021-03-19 13:04 UTC (permalink / raw)
  To: ltp

Hi Amir,

> Hi Petr,

> Following tests were used for development of the two features
> queued for v5.13 (in linux-next):
> - Performance improvements for events merge [1]
> - Unprivileged fanotify listener [2]

As these are features not fixes, I suppose nothing from these already merged 2
patchsets in next tree can be added with struct tst_tag to document it.
I wonder if any of these are could be at least noted in the tests / commit
messages.

> All test cases of fanotify05 pass on upstream, but their runtime
> on linux-next is reduced by more than half.

> Only the first test case of fanotify17 pass on upstream.
> The rest of the test cases as well as fanotify18 and fanotify19
> tests exit with TCONF on upstream. They all pass on linux-next.

Thanks! LGTM, thanks for testing them on both mainline and next tree.

To whole patchset:
Reviewed-by: Petr Vorel <pvorel@suse.cz>

I'll apply it with following tiny fixes to fix compilation on very old kernels
(2.6.x) and to use our documentation format [3] [4].
(+ later I'll fix documentation format for the rest of the tests)

Kind regards,
Petr

> Thanks,
> Amir.

> [1] https://lore.kernel.org/linux-fsdevel/20210304104826.3993892-1-amir73il@gmail.com/
> [2] https://lore.kernel.org/linux-fsdevel/20210304112921.3996419-1-amir73il@gmail.com/

[3] https://github.com/linux-test-project/ltp/releases/download/20210121/metadata.20210121.pdf
[4] https://github.com/linux-test-project/ltp/releases/download/20210121/metadata.20210121.html

diff --git testcases/kernel/syscalls/fanotify/fanotify17.c testcases/kernel/syscalls/fanotify/fanotify17.c
index ee242a441..98355a7b4 100644
--- testcases/kernel/syscalls/fanotify/fanotify17.c
+++ testcases/kernel/syscalls/fanotify/fanotify17.c
@@ -7,13 +7,15 @@
  * Forked from getxattr05.c by Amir Goldstein <amir73il@gmail.com>
  */
 
-/*
- * DESCRIPTION
- *     Check that fanotify groups and marks limits are enforced correctly.
- *     If user ns is supported, verify that global limit and per user ns
- *     limits are both enforced.
- *     Otherwise, we only check that global groups limit is enforced.
+/*\
+ * [Description]
+ *
+ * Check that fanotify groups and marks limits are enforced correctly.
+ * If user ns is supported, verify that global limit and per user ns
+ * limits are both enforced.
+ * Otherwise, we only check that global groups limit is enforced.
  */
+
 #define _GNU_SOURCE
 #include "config.h"
 #include <errno.h>
diff --git testcases/kernel/syscalls/fanotify/fanotify18.c testcases/kernel/syscalls/fanotify/fanotify18.c
index 1acd23ce2..318245efc 100644
--- testcases/kernel/syscalls/fanotify/fanotify18.c
+++ testcases/kernel/syscalls/fanotify/fanotify18.c
@@ -3,13 +3,17 @@
  * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
  *
  * Started by Matthew Bobrowski <mbobrowski@mbobrowski.org>
+ */
+
+/*\
+ * [Description]
  *
- * DESCRIPTION
- *	This set of tests is to ensure that the unprivileged listener feature of
- *	fanotify is functioning as expected. The objective this test case file
- *	is to validate whether any forbidden flags that are passed by an
- *	unprivileged user return the correct error result.
+ * This set of tests is to ensure that the unprivileged listener feature of
+ * fanotify is functioning as expected. The objective this test case file
+ * is to validate whether any forbidden flags that are passed by an
+ * unprivileged user return the correct error result.
  */
+
 #define _GNU_SOURCE
 #include "config.h"
 
@@ -17,10 +21,9 @@
 #include <stdio.h>
 #include <errno.h>
 #include "tst_test.h"
-#include "fanotify.h"
 
-#if defined(HAVE_SYS_FANOTIFY_H)
-#include <sys/fanotify.h>
+#ifdef HAVE_SYS_FANOTIFY_H
+#include "fanotify.h"
 
 /*
  * This is a set of intialization flags that are not permitted to be used by an
@@ -194,5 +197,5 @@ static struct tst_test test = {
 };
 
 #else
-	TST_TEST_CONF("System does not have required fanotify support");
+	TST_TEST_TCONF("system doesn't have required fanotify support");
 #endif
diff --git testcases/kernel/syscalls/fanotify/fanotify19.c testcases/kernel/syscalls/fanotify/fanotify19.c
index 83a9aaa98..92ed45e49 100644
--- testcases/kernel/syscalls/fanotify/fanotify19.c
+++ testcases/kernel/syscalls/fanotify/fanotify19.c
@@ -3,14 +3,18 @@
  * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
  *
  * Started by Matthew Bobrowski <mbobrowski@mbobrowski.org>
+ */
+
+/*\
+ * [Description]
  *
- * DESCRIPTION
- *	This set of tests is to ensure that the unprivileged listener feature of
- *	fanotify is functioning as expected. The objective of this test file is
- *	to generate a sequence of events and ensure that the returned events
- *	contain the limited values that an unprivileged listener is expected
- *	to receive.
+ * This set of tests is to ensure that the unprivileged listener feature of
+ * fanotify is functioning as expected. The objective of this test file is
+ * to generate a sequence of events and ensure that the returned events
+ * contain the limited values that an unprivileged listener is expected
+ * to receive.
  */
+
 #define _GNU_SOURCE
 #include "config.h"
 
@@ -21,10 +25,9 @@
 #include <sys/wait.h>
 
 #include "tst_test.h"
-#include "fanotify.h"
 
-#if defined(HAVE_SYS_FANOTIFY_H)
-#include <sys/fanotify.h>
+#ifdef HAVE_SYS_FANOTIFY_H
+#include "fanotify.h"
 
 #define EVENT_MAX 1024
 #define EVENT_SIZE (sizeof (struct fanotify_event_metadata))
@@ -249,5 +252,5 @@ static struct tst_test test = {
 };
 
 #else
-	TST_TEST_CONF("System does not have required fanotify support");
+	TST_TEST_TCONF("system doesn't have required fanotify support");
 #endif

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 0/8] fanotify tests for v5.13
  2021-03-19 13:04 ` [LTP] [PATCH 0/8] fanotify tests for v5.13 Petr Vorel
@ 2021-03-19 13:54   ` Amir Goldstein
  2021-03-21 20:13     ` Petr Vorel
  0 siblings, 1 reply; 15+ messages in thread
From: Amir Goldstein @ 2021-03-19 13:54 UTC (permalink / raw)
  To: ltp

On Fri, Mar 19, 2021 at 3:04 PM Petr Vorel <pvorel@suse.cz> wrote:
>
> Hi Amir,
>
> > Hi Petr,
>
> > Following tests were used for development of the two features
> > queued for v5.13 (in linux-next):
> > - Performance improvements for events merge [1]
> > - Unprivileged fanotify listener [2]
>
> As these are features not fixes, I suppose nothing from these already merged 2
> patchsets in next tree can be added with struct tst_tag to document it.
> I wonder if any of these are could be at least noted in the tests / commit
> messages.
>

Whatever you think is best for your project users.
If you want to document the commits that added the features, I suggest
that you wait until those commits hit master (next cycle).
These are the relevant commit subjects:

   fanotify: configurable limits via sysfs
   fanotify: support limited functionality for unprivileged users

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 0/8] fanotify tests for v5.13
  2021-03-19 13:54   ` Amir Goldstein
@ 2021-03-21 20:13     ` Petr Vorel
  2021-03-22 18:42       ` Amir Goldstein
  0 siblings, 1 reply; 15+ messages in thread
From: Petr Vorel @ 2021-03-21 20:13 UTC (permalink / raw)
  To: ltp

Hi Amir,

> Whatever you think is best for your project users.
> If you want to document the commits that added the features, I suggest
> that you wait until those commits hit master (next cycle).
> These are the relevant commit subjects:

>    fanotify: configurable limits via sysfs
>    fanotify: support limited functionality for unprivileged users

Thanks a lot!
IMHO being in next tree should be ok (commits hashes should be kept).

FYI next week I'm busy due hackweek, thus I'll probably merge this after.

Kind regards,
Petr

[1] http://lists.linux.it/pipermail/ltp/2021-March/021637.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 0/8] fanotify tests for v5.13
  2021-03-21 20:13     ` Petr Vorel
@ 2021-03-22 18:42       ` Amir Goldstein
  2021-03-22 19:07         ` Petr Vorel
  2021-03-23  6:36         ` Petr Vorel
  0 siblings, 2 replies; 15+ messages in thread
From: Amir Goldstein @ 2021-03-22 18:42 UTC (permalink / raw)
  To: ltp

On Sun, Mar 21, 2021 at 10:13 PM Petr Vorel <pvorel@suse.cz> wrote:
>
> Hi Amir,
>
> > Whatever you think is best for your project users.
> > If you want to document the commits that added the features, I suggest
> > that you wait until those commits hit master (next cycle).
> > These are the relevant commit subjects:
>
> >    fanotify: configurable limits via sysfs
> >    fanotify: support limited functionality for unprivileged users
>
> Thanks a lot!
> IMHO being in next tree should be ok (commits hashes should be kept).
>

There is no such guarantee, certainly not so far from the v5.13 merge
window, so I advise against including the commit ids at this point.
The commit subject is descriptive enough IMO and you can add commit
ids later on if you think it is necessary.

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 0/8] fanotify tests for v5.13
  2021-03-22 18:42       ` Amir Goldstein
@ 2021-03-22 19:07         ` Petr Vorel
  2021-03-23  6:36         ` Petr Vorel
  1 sibling, 0 replies; 15+ messages in thread
From: Petr Vorel @ 2021-03-22 19:07 UTC (permalink / raw)
  To: ltp

Hi Amir,

> > > Whatever you think is best for your project users.
> > > If you want to document the commits that added the features, I suggest
> > > that you wait until those commits hit master (next cycle).
> > > These are the relevant commit subjects:

> > >    fanotify: configurable limits via sysfs
> > >    fanotify: support limited functionality for unprivileged users

> > Thanks a lot!
> > IMHO being in next tree should be ok (commits hashes should be kept).


> There is no such guarantee, certainly not so far from the v5.13 merge
> window, so I advise against including the commit ids at this point.
> The commit subject is descriptive enough IMO and you can add commit
> ids later on if you think it is necessary.

OK, make sense to wait with commit hashes. I'll merge it tomorrow as is (with
that formatting and fixing old kernel changes I posted earlier).

Kind regards,
Petr

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [LTP] [PATCH 0/8] fanotify tests for v5.13
  2021-03-22 18:42       ` Amir Goldstein
  2021-03-22 19:07         ` Petr Vorel
@ 2021-03-23  6:36         ` Petr Vorel
  1 sibling, 0 replies; 15+ messages in thread
From: Petr Vorel @ 2021-03-23  6:36 UTC (permalink / raw)
  To: ltp

Hi Amir,

> > > Whatever you think is best for your project users.
> > > If you want to document the commits that added the features, I suggest
> > > that you wait until those commits hit master (next cycle).
> > > These are the relevant commit subjects:

> > >    fanotify: configurable limits via sysfs
> > >    fanotify: support limited functionality for unprivileged users

> > Thanks a lot!
> > IMHO being in next tree should be ok (commits hashes should be kept).


> There is no such guarantee, certainly not so far from the v5.13 merge
> window, so I advise against including the commit ids at this point.
> The commit subject is descriptive enough IMO and you can add commit
> ids later on if you think it is necessary.

Merged + updated doc formatting for our doc generation.
Thanks for your work!

Kind regards,
Petr

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2021-03-23  6:36 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-18 13:11 [LTP] [PATCH 0/8] fanotify tests for v5.13 Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 1/8] syscalls/fanotify05: Fix test output when not getting overflow Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 2/8] syscalls/fanotify05: Verify events are received by queue order Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 3/8] syscalls/fanotify05: Verify getting a single overflow event Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 4/8] syscalls/fanotify05: Add a test case for unlimited queue Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 5/8] syscalls/fanotify05: adjust test to tunable max_queued_events Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 6/8] syscalls/fanotify: New test for fanotify user limits Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 7/8] syscalls/fanotify: New test to validate unprivileged user permissions Amir Goldstein
2021-03-18 13:11 ` [LTP] [PATCH 8/8] syscalls/fanotify: New test to validate unprivileged listener events Amir Goldstein
2021-03-19 13:04 ` [LTP] [PATCH 0/8] fanotify tests for v5.13 Petr Vorel
2021-03-19 13:54   ` Amir Goldstein
2021-03-21 20:13     ` Petr Vorel
2021-03-22 18:42       ` Amir Goldstein
2021-03-22 19:07         ` Petr Vorel
2021-03-23  6:36         ` Petr Vorel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.