From: Wei Gao via ltp <ltp@lists.linux.it>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH v7] mremap07.c: New test for mremap() with MREMAP_DONTUNMAP
Date: Fri, 17 Apr 2026 06:53:25 +0000 [thread overview]
Message-ID: <20260417065332.23663-1-wegao@suse.com> (raw)
In-Reply-To: <20260410023201.18119-1-wegao@suse.com>
This test verifies the mremap() syscall with the MREMAP_DONTUNMAP flag.
It uses userfaultfd to verify that accessing the old memory region
correctly triggers a page fault after the mapping has been moved.
MREMAP_DONTUNMAP behavior with userfaultfd was not covered by existing
mremap tests. This test provides coverage for the feature requested in
the linked issue.
Fixes: https://github.com/linux-test-project/ltp/issues/1168
Signed-off-by: Wei Gao <wegao@suse.com>
---
v6->v7:
- Update commit description
- Update year of copyright
configure.ac | 1 +
runtest/syscalls | 1 +
testcases/kernel/syscalls/mremap/.gitignore | 1 +
testcases/kernel/syscalls/mremap/Makefile | 1 +
testcases/kernel/syscalls/mremap/mremap07.c | 158 ++++++++++++++++++++
5 files changed, 162 insertions(+)
create mode 100644 testcases/kernel/syscalls/mremap/mremap07.c
diff --git a/configure.ac b/configure.ac
index 812f17d8b..211aaa8ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,6 +46,7 @@ AC_CHECK_DECLS([MADV_MERGEABLE],,,[#include <sys/mman.h>])
AC_CHECK_DECLS([NFTA_CHAIN_ID, NFTA_VERDICT_CHAIN_ID],,,[#include <linux/netfilter/nf_tables.h>])
AC_CHECK_DECLS([PR_CAPBSET_DROP, PR_CAPBSET_READ],,,[#include <sys/prctl.h>])
AC_CHECK_DECLS([SEM_STAT_ANY],,,[#include <sys/sem.h>])
+AC_CHECK_DECLS([MREMAP_DONTUNMAP],,,[#include <linux/mman.h>])
AC_CHECK_HEADERS_ONCE([ \
aio.h \
diff --git a/runtest/syscalls b/runtest/syscalls
index d72fceb5e..b9a9ce5fe 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -927,6 +927,7 @@ mremap03 mremap03
mremap04 mremap04
mremap05 mremap05
mremap06 mremap06
+mremap07 mremap07
mseal01 mseal01
mseal02 mseal02
diff --git a/testcases/kernel/syscalls/mremap/.gitignore b/testcases/kernel/syscalls/mremap/.gitignore
index ec15a19cd..292899e03 100644
--- a/testcases/kernel/syscalls/mremap/.gitignore
+++ b/testcases/kernel/syscalls/mremap/.gitignore
@@ -4,3 +4,4 @@
/mremap04
/mremap05
/mremap06
+/mremap07
diff --git a/testcases/kernel/syscalls/mremap/Makefile b/testcases/kernel/syscalls/mremap/Makefile
index 9f5aca9ec..8811b887e 100644
--- a/testcases/kernel/syscalls/mremap/Makefile
+++ b/testcases/kernel/syscalls/mremap/Makefile
@@ -8,5 +8,6 @@ LTPLIBS = ipc
include $(top_srcdir)/include/mk/testcases.mk
mremap04: LTPLDLIBS = -lltpipc
+mremap07: LDLIBS += -lpthread
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/mremap/mremap07.c b/testcases/kernel/syscalls/mremap/mremap07.c
new file mode 100644
index 000000000..102136322
--- /dev/null
+++ b/testcases/kernel/syscalls/mremap/mremap07.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Wei Gao <wegao@suse.com>
+ */
+
+/*\
+ * LTP test case for mremap() with MREMAP_DONTUNMAP and userfaultfd.
+ *
+ * Test mremap() with MREMAP_DONTUNMAP and verify that accessing the
+ * old memory region triggers a page fault, which is then correctly
+ * handled by a userfaultfd handler.
+ */
+
+#define _GNU_SOURCE
+#include <poll.h>
+#include <pthread.h>
+#include <linux/mman.h>
+
+#include "tst_test.h"
+#include "tst_safe_pthread.h"
+#include "lapi/userfaultfd.h"
+#include "config.h"
+
+#if HAVE_DECL_MREMAP_DONTUNMAP
+
+static int page_size;
+static int uffd = -1;
+static char *fault_addr;
+static char *new_remap_addr;
+
+static const char *test_string = "Hello, world! This is a test string that fills up a page.";
+
+static void *fault_handler_thread(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ struct uffd_msg msg;
+ struct uffdio_copy uffdio_copy;
+
+ TST_CHECKPOINT_WAIT(0);
+
+ struct pollfd pollfd;
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+
+ int nready = poll(&pollfd, 1, -1);
+
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "poll() failed");
+
+ if (nready == 0)
+ tst_brk(TBROK, "poll() timed out unexpectedly");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TBROK, "Received unexpected UFFD_EVENT: %d", msg.event);
+
+ if ((char *)msg.arg.pagefault.address != fault_addr)
+ tst_brk(TBROK, "Page fault on unexpected address: %p", (void *)msg.arg.pagefault.address);
+
+ tst_res(TINFO, "Userfaultfd handler caught a page fault at %p", (void *)msg.arg.pagefault.address);
+
+ uffdio_copy.src = (unsigned long)new_remap_addr;
+ uffdio_copy.dst = (unsigned long)fault_addr;
+ uffdio_copy.len = page_size;
+ uffdio_copy.mode = 0;
+ uffdio_copy.copy = 0;
+
+ SAFE_IOCTL(uffd, UFFDIO_COPY, &uffdio_copy);
+ tst_res(TPASS, "Userfaultfd handler successfully handled the fault");
+
+ return NULL;
+}
+
+static void setup(void)
+{
+ page_size = getpagesize();
+ struct uffdio_api uffdio_api;
+ struct uffdio_register uffdio_register;
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, true);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = 0;
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ fault_addr = SAFE_MMAP(NULL, page_size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ tst_res(TINFO, "Original mapping created at %p", (void *)fault_addr);
+
+ strcpy(fault_addr, "ABCD");
+
+ uffdio_register.range.start = (unsigned long)fault_addr;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+}
+
+static void cleanup(void)
+{
+ if (new_remap_addr && new_remap_addr != MAP_FAILED)
+ SAFE_MUNMAP(new_remap_addr, page_size);
+
+ if (fault_addr && fault_addr != MAP_FAILED)
+ SAFE_MUNMAP(fault_addr, page_size);
+
+ if (uffd != -1)
+ SAFE_CLOSE(uffd);
+}
+
+static void run(void)
+{
+ pthread_t handler_thread;
+
+ SAFE_PTHREAD_CREATE(&handler_thread, NULL,
+ fault_handler_thread, NULL);
+
+ new_remap_addr = mremap(fault_addr, page_size, page_size,
+ MREMAP_DONTUNMAP | MREMAP_MAYMOVE, NULL);
+
+ if (new_remap_addr == MAP_FAILED)
+ tst_brk(TBROK | TERRNO, "mremap failed");
+
+ tst_res(TINFO, "New mapping created at %p", (void *)new_remap_addr);
+
+ strcpy(new_remap_addr, test_string);
+
+ TST_CHECKPOINT_WAKE(0);
+
+ tst_res(TINFO, "Main thread accessing old address %p to trigger fault",
+ (void *)fault_addr);
+
+ (void)*(volatile char *)fault_addr;
+
+ SAFE_PTHREAD_JOIN(handler_thread, NULL);
+
+ TST_EXP_EQ_STR(fault_addr, test_string);
+
+ SAFE_MUNMAP(new_remap_addr, page_size);
+ new_remap_addr = NULL;
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .needs_checkpoints = 1,
+ .cleanup = cleanup,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USERFAULTFD=y",
+ NULL,
+ },
+ .min_kver = "5.7",
+};
+
+#else
+TST_TEST_TCONF("Missing MREMAP_DONTUNMAP in <linux/mman.h>");
+#endif
--
2.52.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
next prev parent reply other threads:[~2026-04-17 6:54 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-27 23:02 [LTP] [PATCH v1] mremap07.c: New case check mremap with MREMAP_DONTUNMAP Wei Gao via ltp
2025-10-15 3:15 ` [LTP] [PATCH v2] " Wei Gao via ltp
2025-10-16 13:32 ` Petr Vorel
2025-10-17 7:51 ` Wei Gao via ltp
2025-10-30 19:39 ` Petr Vorel
2025-11-01 8:47 ` Wei Gao via ltp
2025-10-30 5:40 ` [LTP] [PATCH v3] " Wei Gao via ltp
2025-10-30 20:07 ` Petr Vorel
2026-02-25 9:05 ` [LTP] [PATCH v4] " Wei Gao via ltp
2026-03-23 7:03 ` Andrea Cervesato via ltp
2026-03-25 1:15 ` [LTP] [PATCH v5] " Wei Gao via ltp
2026-03-26 10:01 ` Andrea Cervesato via ltp
2026-04-10 2:31 ` [LTP] [PATCH v6] " Wei Gao via ltp
2026-04-17 6:53 ` Wei Gao via ltp [this message]
2026-04-17 7:55 ` [LTP] mremap07.c: New test for mremap() " linuxtestproject.agent
2026-04-17 8:00 ` Andrea Cervesato via ltp
2026-04-17 12:27 ` [LTP] [PATCH v8] " Wei Gao via ltp
2026-04-17 13:26 ` [LTP] " linuxtestproject.agent
2026-04-19 1:22 ` Wei Gao via ltp
2026-04-20 10:12 ` [LTP] [PATCH v8] " Li Wang
2026-04-21 8:20 ` Wei Gao via ltp
2026-04-21 9:11 ` Li Wang
2026-04-22 2:30 ` [LTP] [PATCH v9] " Wei Gao via ltp
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260417065332.23663-1-wegao@suse.com \
--to=ltp@lists.linux.it \
--cc=wegao@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.