---
 test/Makefile.am     |    9 +++
 test/revoke-devmem.c |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+)
 create mode 100644 test/revoke-devmem.c

diff --git a/test/Makefile.am b/test/Makefile.am
index 1d24a65ded8b..1dcaa1eb6da5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -56,6 +56,7 @@ TESTS +=\
        dax-xfs.sh \
        align.sh \
        device-dax \
+       revoke-devmem \
        device-dax-fio.sh \
        daxctl-devices.sh \
        dm.sh \
@@ -71,6 +72,7 @@ check_PROGRAMS +=\
        dax-dev \
        dax-pmd \
        device-dax \
+       revoke-devmem \
        mmap
 endif
 
@@ -154,6 +156,13 @@ device_dax_LDADD = \
                 $(UUID_LIBS) \
                ../libutil.a
 
+revoke_devmem_SOURCES = \
+               revoke-devmem.c \
+               dax-dev.c \
+               $(testcore)
+
+revoke_devmem_LDADD = $(LIBNDCTL_LIB)
+
 smart_notify_SOURCES = smart-notify.c
 smart_notify_LDADD = $(LIBNDCTL_LIB)
 smart_listen_SOURCES = smart-listen.c
diff --git a/test/revoke-devmem.c b/test/revoke-devmem.c
new file mode 100644
index 000000000000..ffa509e2d7d1
--- /dev/null
+++ b/test/revoke-devmem.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2020 Intel Corporation. All rights reserved. */
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <util/size.h>
+#include <linux/falloc.h>
+#include <linux/version.h>
+#include <ndctl/libndctl.h>
+#include <ccan/array_size/array_size.h>
+
+#include <builtin.h>
+#include <test.h>
+
+static sigjmp_buf sj_env;
+
+static void sigbus(int sig, siginfo_t *siginfo, void *d)
+{
+       siglongjmp(sj_env, 1);
+}
+
+#define err(fmt, ...) \
+       fprintf(stderr, "%s: " fmt, __func__, ##__VA_ARGS__)
+
+static int test_devmem(int loglevel, struct ndctl_test *test,
+               struct ndctl_ctx *ctx)
+{
+       void *buf;
+       int fd, rc;
+       struct sigaction act;
+       unsigned long long resource;
+       struct ndctl_namespace *ndns;
+
+       ndctl_set_log_priority(ctx, loglevel);
+
+       /* iostrict devmem started in kernel 4.5 */
+       if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 5, 0)))
+               return 77;
+
+       ndns = ndctl_get_test_dev(ctx);
+       if (!ndns) {
+               err("failed to find suitable namespace\n");
+               return 77;
+       }
+
+       resource = ndctl_namespace_get_resource(ndns);
+       if (resource == ULLONG_MAX) {
+               err("failed to retrieve resource base\n");
+               return 77;
+       }
+
+       rc = ndctl_namespace_disable(ndns);
+       if (rc) {
+               err("failed to disable namespace\n");
+               return rc;
+       }
+
+       /* establish a devmem mapping of the namespace memory */
+       fd = open("/dev/mem", O_RDWR);
+       if (fd < 0) {
+               err("failed to open /dev/mem: %s\n", strerror(errno));
+               rc = -errno;
+               goto out_devmem;
+       }
+
+       buf = mmap(NULL, SZ_2M, PROT_READ|PROT_WRITE, MAP_SHARED, fd, resource);
+       if (buf == MAP_FAILED) {
+               err("failed to map /dev/mem: %s\n", strerror(errno));
+               rc = -errno;
+               goto out_mmap;
+       }
+
+       /* populate and write, should not fail */
+       memset(buf, 0, SZ_2M);
+
+       memset(&act, 0, sizeof(act));
+       act.sa_sigaction = sigbus;
+       act.sa_flags = SA_SIGINFO;
+       if (sigaction(SIGBUS, &act, 0)) {
+               perror("sigaction");
+               rc = EXIT_FAILURE;
+               goto out_sigaction;
+       }
+
+       /* test fault due to devmem revocation */
+       if (sigsetjmp(sj_env, 1)) {
+               /* got sigbus, success */
+               fprintf(stderr, "devmem revoked!\n");
+               rc = 0;
+               goto out_sigaction;
+       }
+
+       rc = ndctl_namespace_enable(ndns);
+       if (rc) {
+               err("failed to enable namespace\n");
+               goto out_sigaction;
+       }
+
+       /* write, should sigbus */
+       memset(buf, 0, SZ_2M);
+
+       err("kernel failed to prevent write after namespace enabled\n");
+       rc = -ENXIO;
+
+out_sigaction:
+       munmap(buf, SZ_2M);
+out_mmap:
+       close(fd);
+out_devmem:
+       if (ndctl_namespace_enable(ndns) != 0)
+               err("failed to re-enable namespace\n");
+       return rc;
+}
+
+int main(int argc, char *argv[])
+{
+       struct ndctl_test *test = ndctl_test_new(0);
+       struct ndctl_ctx *ctx;
+       int rc;
+
+       if (!test) {
+               fprintf(stderr, "failed to initialize test\n");
+               return EXIT_FAILURE;
+       }
+
+       rc = ndctl_new(&ctx);
+       if (rc < 0)
+               return ndctl_test_result(test, rc);
+
+       rc = test_devmem(LOG_DEBUG, test, ctx);
+       ndctl_unref(ctx);
+       return ndctl_test_result(test, rc);
+}
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to