* [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON
@ 2026-03-02 12:02 Ricardo Branco
2026-03-02 15:00 ` Cyril Hrubis
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Ricardo Branco @ 2026-03-02 12:02 UTC (permalink / raw)
To: ltp
Signed-off-by: Ricardo Branco <rbranco@suse.de>
---
configure.ac | 1 +
include/lapi/userfaultfd.h | 13 ++
runtest/syscalls | 1 +
.../kernel/syscalls/userfaultfd/.gitignore | 1 +
.../kernel/syscalls/userfaultfd/Makefile | 1 +
.../syscalls/userfaultfd/userfaultfd06.c | 144 ++++++++++++++++++
6 files changed, 161 insertions(+)
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd06.c
diff --git a/configure.ac b/configure.ac
index 7fa614dcb..94bcbcc98 100644
--- a/configure.ac
+++ b/configure.ac
@@ -278,6 +278,7 @@ AC_CHECK_TYPES([struct sockaddr_vm],,,[
])
AC_CHECK_TYPES([struct uffdio_move],,,[#include <linux/userfaultfd.h>])
+AC_CHECK_TYPES([struct uffdio_poison],,,[#include <linux/userfaultfd.h>])
AC_CHECK_TYPES([struct uffdio_writeprotect],,,[#include <linux/userfaultfd.h>])
# Tools knobs
diff --git a/include/lapi/userfaultfd.h b/include/lapi/userfaultfd.h
index 0c9e34c84..aab3890b7 100644
--- a/include/lapi/userfaultfd.h
+++ b/include/lapi/userfaultfd.h
@@ -233,6 +233,19 @@ struct uffdio_writeprotect {
};
#endif /* HAVE_STRUCT_UFFDIO_WRITEPROTECT */
+#ifndef HAVE_STRUCT_UFFDIO_POISON
+#define UFFD_FEATURE_POISON (1<<14)
+#define _UFFDIO_POISON (0x08)
+#define UFFDIO_POISON _IOWR(UFFDIO, _UFFDIO_POISON, \
+ struct uffdio_poison)
+struct uffdio_poison {
+ struct uffdio_range range;
+#define UFFDIO_POISON_MODE_DONTWAKE ((__u64)1<<0)
+ __u64 mode;
+ __s64 updated;
+};
+#endif /* HAVE_STRUCT_UFFDIO_POISON */
+
#define SAFE_USERFAULTFD(flags, retry) \
safe_userfaultfd(__FILE__, __LINE__, (flags), (retry))
diff --git a/runtest/syscalls b/runtest/syscalls
index 05bb3ceb1..b76c3890f 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1775,6 +1775,7 @@ userfaultfd02 userfaultfd02
userfaultfd03 userfaultfd03
userfaultfd04 userfaultfd04
userfaultfd05 userfaultfd05
+userfaultfd06 userfaultfd06
ustat01 ustat01
ustat02 ustat02
diff --git a/testcases/kernel/syscalls/userfaultfd/.gitignore b/testcases/kernel/syscalls/userfaultfd/.gitignore
index fb2ae243b..bc32fdf3b 100644
--- a/testcases/kernel/syscalls/userfaultfd/.gitignore
+++ b/testcases/kernel/syscalls/userfaultfd/.gitignore
@@ -3,3 +3,4 @@
/userfaultfd03
/userfaultfd04
/userfaultfd05
+/userfaultfd06
diff --git a/testcases/kernel/syscalls/userfaultfd/Makefile b/testcases/kernel/syscalls/userfaultfd/Makefile
index 96650a65a..3252e47df 100644
--- a/testcases/kernel/syscalls/userfaultfd/Makefile
+++ b/testcases/kernel/syscalls/userfaultfd/Makefile
@@ -16,3 +16,4 @@ userfaultfd02: CFLAGS += -pthread
userfaultfd03: CFLAGS += -pthread
userfaultfd04: CFLAGS += -pthread
userfaultfd05: CFLAGS += -pthread
+userfaultfd06: CFLAGS += -pthread
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd06.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd06.c
new file mode 100644
index 000000000..5b1252c35
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd06.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 SUSE LLC
+ * Author: Ricardo Branco <rbranco@suse.com>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different thread testing UFFDIO_POISON.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_safe_pthread.h"
+#include "lapi/userfaultfd.h"
+
+static int page_size;
+static char *page;
+static int uffd;
+static int poison_fault_seen;
+static volatile int sigbus_seen;
+static sigjmp_buf jmpbuf;
+
+static void sigbus_handler(int sig)
+{
+ if (sig == SIGBUS) {
+ sigbus_seen = 1;
+ siglongjmp(jmpbuf, 1);
+ }
+}
+
+static void setup(void)
+{
+ struct sigaction sa = {};
+
+ sa.sa_handler = sigbus_handler;
+ sigemptyset(&sa.sa_mask);
+ SAFE_SIGACTION(SIGBUS, &sa, NULL);
+}
+
+static void set_pages(void)
+{
+ page_size = sysconf(_SC_PAGE_SIZE);
+ page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void reset_pages(void)
+{
+ if (page) {
+ SAFE_MUNMAP(page, page_size);
+ page = NULL;
+ }
+}
+
+static void *handle_thread(void)
+{
+ static struct uffd_msg msg;
+ struct uffdio_poison uffdio_poison = {};
+ struct pollfd pollfd;
+ int nready;
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TFAIL, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ tst_atomic_store(1, &poison_fault_seen);
+
+ /* Poison the page that triggered the fault */
+ uffdio_poison.range.start = msg.arg.pagefault.address & ~(page_size - 1);
+ uffdio_poison.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_POISON, &uffdio_poison);
+
+ close(uffd);
+ return NULL;
+}
+
+static void run(void)
+{
+ pthread_t thr;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+ char dummy;
+
+ poison_fault_seen = 0;
+ sigbus_seen = 0;
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, false);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = UFFD_FEATURE_POISON;
+
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ if (!(uffdio_api.features & UFFD_FEATURE_POISON))
+ tst_brk(TCONF, "UFFD_FEATURE_POISON not supported");
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
+
+ /* Try to read from the page: should trigger fault, get poisoned, then SIGBUS */
+ if (sigsetjmp(jmpbuf, 1) == 0) {
+ LTP_VAR_USED(dummy) = page[0];
+ }
+
+ SAFE_PTHREAD_JOIN(thr, NULL);
+ reset_pages();
+
+ int poisoned = tst_atomic_load(&poison_fault_seen);
+
+ if (poisoned && sigbus_seen)
+ tst_res(TPASS, "POISON successfully triggered SIGBUS");
+ else if (poisoned && !sigbus_seen)
+ tst_res(TFAIL, "POISON fault seen but no SIGBUS received");
+ else if (!poisoned && sigbus_seen)
+ tst_res(TFAIL, "SIGBUS received but no poison fault seen");
+ else
+ tst_res(TFAIL, "No poison fault or SIGBUS observed");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = reset_pages,
+};
--
2.53.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON
2026-03-02 12:02 [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON Ricardo Branco
@ 2026-03-02 15:00 ` Cyril Hrubis
2026-03-12 13:13 ` Andrea Cervesato via ltp
2026-03-20 12:15 ` Andrea Cervesato via ltp
2 siblings, 0 replies; 4+ messages in thread
From: Cyril Hrubis @ 2026-03-02 15:00 UTC (permalink / raw)
To: Ricardo Branco; +Cc: ltp
Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON
2026-03-02 12:02 [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON Ricardo Branco
2026-03-02 15:00 ` Cyril Hrubis
@ 2026-03-12 13:13 ` Andrea Cervesato via ltp
2026-03-20 12:15 ` Andrea Cervesato via ltp
2 siblings, 0 replies; 4+ messages in thread
From: Andrea Cervesato via ltp @ 2026-03-12 13:13 UTC (permalink / raw)
To: Ricardo Branco, ltp
Hi!
> +
> +static void reset_pages(void)
> +{
> + if (page) {
> + SAFE_MUNMAP(page, page_size);
> + page = NULL;
> + }
> +}
> +
> +static void *handle_thread(void)
It looks good, but I noticed that all threads handlers in the userfaultfd testing
suite are not using the POSIX syntax:
static void *handle_thread(void *arg LTP_ATTRIBUTE_UNUSED)
We should can change it later on.
Acked-by: Andrea Cervesato <andrea.cervesato@suse.com>
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON
2026-03-02 12:02 [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON Ricardo Branco
2026-03-02 15:00 ` Cyril Hrubis
2026-03-12 13:13 ` Andrea Cervesato via ltp
@ 2026-03-20 12:15 ` Andrea Cervesato via ltp
2 siblings, 0 replies; 4+ messages in thread
From: Andrea Cervesato via ltp @ 2026-03-20 12:15 UTC (permalink / raw)
To: Ricardo Branco; +Cc: ltp
Merged, thanks.
Regards,
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-20 12:15 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-02 12:02 [LTP] [PATCH v8] userfaultfd: Add test using UFFDIO_POISON Ricardo Branco
2026-03-02 15:00 ` Cyril Hrubis
2026-03-12 13:13 ` Andrea Cervesato via ltp
2026-03-20 12:15 ` Andrea Cervesato via ltp
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.