[LTP] [PATCH 4/5] syscalls/fanotify12: add new test for FAN_OPEN_EXEC event mask
Matthew Bobrowski
mbobrowski@mbobrowski.org
Tue Jan 22 23:36:27 CET 2019
* Defined FAN_OPEN_EXEC flag in local fanotify header file in case the
user space system header files do not have this event type defined
* Added a new test file fanotify12 that contains the necessary test
cases to support and test the FAN_OPEN_EXEC event mask
Signed-off-by: Matthew Bobrowski <mbobrowski@mbobrowski.org>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
---
testcases/kernel/syscalls/fanotify/.gitignore | 1 +
testcases/kernel/syscalls/fanotify/fanotify.h | 3 +
testcases/kernel/syscalls/fanotify/fanotify12.c | 282 ++++++++++++++++++++++++
3 files changed, 286 insertions(+)
create mode 100644 testcases/kernel/syscalls/fanotify/fanotify12.c
diff --git a/testcases/kernel/syscalls/fanotify/.gitignore b/testcases/kernel/syscalls/fanotify/.gitignore
index e08310ed4..4256b8cd3 100644
--- a/testcases/kernel/syscalls/fanotify/.gitignore
+++ b/testcases/kernel/syscalls/fanotify/.gitignore
@@ -9,4 +9,5 @@
/fanotify09
/fanotify10
/fanotify11
+/fanotify12
/fanotify_child
diff --git a/testcases/kernel/syscalls/fanotify/fanotify.h b/testcases/kernel/syscalls/fanotify/fanotify.h
index c77e7a4ac..e5cc59232 100644
--- a/testcases/kernel/syscalls/fanotify/fanotify.h
+++ b/testcases/kernel/syscalls/fanotify/fanotify.h
@@ -64,6 +64,9 @@ static long fanotify_mark(int fd, unsigned int flags, uint64_t mask,
#ifndef FAN_MARK_FILESYSTEM
#define FAN_MARK_FILESYSTEM 0x00000100
#endif
+#ifndef FAN_OPEN_EXEC
+#define FAN_OPEN_EXEC 0x00001000
+#endif
#ifndef FAN_OPEN_EXEC_PERM
#define FAN_OPEN_EXEC_PERM 0x00040000
#endif
diff --git a/testcases/kernel/syscalls/fanotify/fanotify12.c b/testcases/kernel/syscalls/fanotify/fanotify12.c
new file mode 100644
index 000000000..e2ae3576a
--- /dev/null
+++ b/testcases/kernel/syscalls/fanotify/fanotify12.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Matthew Bobrowski. All Rights Reserved.
+ *
+ * Started by Matthew Bobrowski <mbobrowski@mbobrowski.org>
+ *
+ * DESCRIPTION
+ * Validate that the newly introduced FAN_OPEN_EXEC mask functions as
+ * expected. The idea is to generate a sequence of open related
+ * actions to ensure that the correct event flags are being set
+ * depending on what event mask was requested when the object was
+ * marked.
+ */
+#define _GNU_SOURCE
+#include "config.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.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_BUF 32
+
+#define BUF_SIZE 256
+#define TEST_APP "fanotify_child"
+
+static pid_t child_pid;
+static char fname[BUF_SIZE];
+static volatile int fd_notify;
+static volatile int complete;
+static char event_buf[EVENT_BUF_LEN];
+
+static struct test_case_t {
+ const char *tname;
+ struct fanotify_mark_type mark;
+ unsigned long long mask;
+ unsigned long long ignore_mask;
+ int event_count;
+ unsigned long long event_set[EVENT_SET_BUF];
+} test_cases[] = {
+ {
+ "inode mark, FAN_OPEN events",
+ INIT_FANOTIFY_MARK_TYPE(INODE),
+ FAN_OPEN,
+ 0,
+ 2,
+ {FAN_OPEN, FAN_OPEN}
+ },
+ {
+ "inode mark, FAN_OPEN_EXEC events",
+ INIT_FANOTIFY_MARK_TYPE(INODE),
+ FAN_OPEN_EXEC,
+ 0,
+ 1,
+ {FAN_OPEN_EXEC}
+ },
+ {
+ "inode mark, FAN_OPEN | FAN_OPEN_EXEC events",
+ INIT_FANOTIFY_MARK_TYPE(INODE),
+ FAN_OPEN | FAN_OPEN_EXEC,
+ 0,
+ 2,
+ {FAN_OPEN, FAN_OPEN | FAN_OPEN_EXEC}
+ },
+ {
+ "inode mark, FAN_OPEN events, ignore FAN_OPEN_EXEC",
+ INIT_FANOTIFY_MARK_TYPE(INODE),
+ FAN_OPEN,
+ FAN_OPEN_EXEC,
+ 2,
+ {FAN_OPEN, FAN_OPEN}
+ },
+ {
+ "inode mark, FAN_OPEN_EXEC events, ignore FAN_OPEN",
+ INIT_FANOTIFY_MARK_TYPE(INODE),
+ FAN_OPEN_EXEC,
+ FAN_OPEN,
+ 1,
+ {FAN_OPEN_EXEC}
+ },
+ {
+ "inode mark, FAN_OPEN | FAN_OPEN_EXEC events, ignore "
+ "FAN_OPEN_EXEC",
+ INIT_FANOTIFY_MARK_TYPE(INODE),
+ FAN_OPEN | FAN_OPEN_EXEC,
+ FAN_OPEN_EXEC,
+ 2,
+ {FAN_OPEN, FAN_OPEN}
+ }
+};
+
+static int generate_events(void)
+{
+ int fd, status;
+
+ child_pid = SAFE_FORK();
+
+ /*
+ * Generate a sequence of events
+ */
+ if (child_pid == 0) {
+ SAFE_CLOSE(fd_notify);
+
+ fd = SAFE_OPEN(fname, O_RDONLY);
+
+ if (fd > 0)
+ SAFE_CLOSE(fd);
+
+ SAFE_EXECL(TEST_APP, TEST_APP, NULL);
+ exit(1);
+ }
+
+ SAFE_WAITPID(child_pid, &status, 0);
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ return 1;
+ return 0;
+}
+
+static int setup_mark(unsigned int n)
+{
+ unsigned int i = 0;
+ struct test_case_t *tc = &test_cases[n];
+ struct fanotify_mark_type *mark = &tc->mark;
+ const char *const files[] = {fname, TEST_APP};
+
+ tst_res(TINFO, "Test #%d: %s", n, tc->tname);
+ fd_notify = SAFE_FANOTIFY_INIT(FAN_CLASS_NOTIF, O_RDONLY);
+
+ for (; i < ARRAY_SIZE(files); i++) {
+ /* Setup normal mark on object */
+ if (fanotify_mark(fd_notify, FAN_MARK_ADD | mark->flag,
+ tc->mask, AT_FDCWD, files[i]) < 0) {
+ if (errno == EINVAL && tc->mask & FAN_OPEN_EXEC) {
+ tst_res(TCONF,
+ "FAN_OPEN_EXEC not supported in "
+ "kernel?");
+ return -1;
+ } else if (errno == EINVAL) {
+ tst_brk(TCONF | TERRNO,
+ "CONFIG_FANOTIFY_ACCESS_PERMISSIONS "
+ "not configured in kernel?");
+ }else {
+ tst_brk(TBROK | TERRNO,
+ "fanotify_mark(%d, FAN_MARK_ADD | %s, "
+ "%llx, AT_FDCWD, %s) failed",
+ fd_notify,
+ mark->name,
+ tc->mask,
+ files[i]);
+ }
+ }
+
+ /* Setup ignore mark on object */
+ if (tc->ignore_mask) {
+ if (fanotify_mark(fd_notify, FAN_MARK_ADD | mark->flag
+ | FAN_MARK_IGNORED_MASK,
+ tc->ignore_mask, AT_FDCWD,
+ files[i]) < 0) {
+ if (errno == EINVAL &&
+ tc->ignore_mask & FAN_OPEN_EXEC) {
+ tst_res(TCONF,
+ "FAN_OPEN_EXEC not supported "
+ "in kernel?");
+ return -1;
+ } else if (errno == EINVAL) {
+ tst_brk(TCONF | TERRNO,
+ "CONFIG_FANOTIFY_ACCESS_"
+ "PERMISSIONS not configured in "
+ "kernel?");
+ } else {
+ tst_brk(TBROK | TERRNO,
+ "fanotify_mark (%d, "
+ "FAN_MARK_ADD | %s "
+ "| FAN_MARK_IGNORED_MASK, "
+ "%llx, AT_FDCWD, %s) failed",
+ fd_notify, mark->name,
+ tc->ignore_mask, files[i]);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void do_test(unsigned int n)
+{
+ int len = 0, event_num = 0;
+ struct test_case_t *tc = &test_cases[n];
+ struct fanotify_event_metadata *event;
+
+ /* Place a mark on the object */
+ if (setup_mark(n) != 0)
+ goto cleanup;
+
+ /* Generate events in child process */
+ if (!generate_events())
+ goto cleanup;
+
+ /* Read available events into buffer */
+ len = SAFE_READ(0, fd_notify, event_buf, EVENT_BUF_LEN);
+
+ event = (struct fanotify_event_metadata *) event_buf;
+
+ /* Process events */
+ while (FAN_EVENT_OK(event, len) && event_num < tc->event_count) {
+ if (event->mask != *(tc->event_set + event_num)) {
+ tst_res(TFAIL,
+ "Received event: mask=%llx (expected %llx, "
+ "pid=%u, fd=%d",
+ (unsigned long long) event->mask,
+ *(tc->event_set + event_num),
+ (unsigned) event->pid,
+ event->fd);
+ } else if (event->pid != child_pid) {
+ tst_res(TFAIL,
+ "Received event: mask=%llx, pid=%u (expected "
+ "%u), fd=%d",
+ (unsigned long long) event->mask,
+ (unsigned) event->pid,
+ (unsigned) child_pid,
+ event->fd);
+ } else {
+ tst_res(TPASS,
+ "Received event: mask=%llx, pid=%u, fd=%d",
+ (unsigned long long) event->mask,
+ (unsigned) event->pid,
+ event->fd);
+ }
+
+ if (event->fd != FAN_NOFD)
+ SAFE_CLOSE(event->fd);
+
+ event_num++;
+ event = FAN_EVENT_NEXT(event, len);
+ }
+
+cleanup:
+ if (fd_notify > 0)
+ SAFE_CLOSE(fd_notify);
+}
+
+static void do_setup(void)
+{
+ sprintf(fname, "fname_%d", getpid());
+ SAFE_FILE_PRINTF(fname, "1");
+}
+
+static void do_cleanup(void)
+{
+ if (fd_notify > 0)
+ SAFE_CLOSE(fd_notify);
+}
+
+static const char *const resource_files[] = {
+ TEST_APP,
+ NULL
+};
+
+static struct tst_test test = {
+ .setup = do_setup,
+ .test = do_test,
+ .tcnt = ARRAY_SIZE(test_cases),
+ .cleanup = do_cleanup,
+ .forks_child = 1,
+ .needs_root = 1,
+ .resource_files = resource_files
+};
+#else
+ TST_TEST_CONF("System does not contain required fanotify support");
+#endif
--
2.16.4
--
Matthew Bobrowski
More information about the ltp
mailing list