* [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling
@ 2026-07-06 8:15 Hongfu Li
2026-07-06 8:15 ` [PATCH v10 1/6] selftests/mm: move pkey selftest helpers to pkey_util.c Hongfu Li
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-06 8:15 UTC (permalink / raw)
To: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah
Cc: jhubbard, joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li, Hongfu Li
The main changes in this series are to refactor shared tracing and assertion
helpers into a common file, unify both pkey selftests on pkey_assert() and
per-test tracing for consistent diagnostics, and add missing mmap() return
checks with MAP_FAILED used throughout for readability and consistency.
Hongfu Li (6):
selftests/mm: move pkey selftest helpers to pkey_util.c
selftests/mm: unify pkey sighandler selftest assertions and tracing
selftests/mm: use pkey_assert on clone_raw failure in pkey test
selftests/mm: add missing mmap() return checks in pkey tests
selftests/mm: add missing pthread_create() return checks in pkey tests
selftests/mm: fix clone cleartid race in pkey sighandler tests
tools/testing/selftests/mm/pkey-helpers.h | 4 +-
tools/testing/selftests/mm/pkey-powerpc.h | 2 +-
.../selftests/mm/pkey_sighandler_tests.c | 115 ++++++++++--------
tools/testing/selftests/mm/pkey_util.c | 90 ++++++++++++++
tools/testing/selftests/mm/protection_keys.c | 99 ++-------------
5 files changed, 165 insertions(+), 145 deletions(-)
---
v10:
- Add patch 6/6 to fix a pre-existing cleartid race: remove unused
settid/cleartid clone flags and wait for the clone child to exit in
the sigsegv test.
v9:
- In patch 1/5, define test_nr, iteration_nr and dprint_in_signal in
pkey_util.c and remove them from protection_keys.c and
pkey_sighandler_tests.c.
- In patch 1/5, cat_into_file() used the wrong argument in the open()
failure message; print file instead of str. Update the commit message
accordingly.
- In patch 2/5, align clone_raw() continuation lines to the opening parenthesis.
- In patch 5/5, set errno from pthread_create() return value before
pkey_assert(0) on thread creation failure.
- Add Acked-by, Reviewed-by and Tested-by tags to each patch.
v8:
- No code changes (relative to v7).
- Updated Cc list: added developers identified via `git blame` and
`git log` on tools/testing/selftests/mm/pkey*
v7:
- As previously suggested, wait for v7.2-rc1 and rebased the whole series
on top of it. No functional code changes.
v6:
- Add missing pthread_create() return checks (new patch 5/5).
- In patch 2/5, call tracing_off() at the start of test_pkru_sigreturn
before the SIGSEGV handler is reset to SIG_DFL, to avoid leaving ftrace
enabled on crash.
v5:
- Use ret instead of child_pid to hold the return value of clone_raw().
- Make tracing_on(), tracing_off() non-static.
Remove cat_into_file() declaration from pkey-helpers.h.
v4:
- Base changes on top of the latest mm-unstable branch.
- Split the first patch into three:
patch 1: move pkey selftest helpers to shared code;
patch 2: unify sighandler selftest assertions and per-test tracing;
patch 3: use pkey_assert() on clone_raw() failure.
- Use ksft_exit_fail_perror() in main() for mmap() failure.
v3:
- Use pkey_assert() for remaining sigaction() and clone_raw() error
checks for consistency.
v2:
- Update commit message
- Move shared tracing and assertion helpers to a common file,
replace assert() with pkey_assert() in sighandler tests
- Drop assert() from main() in protection_keys.c and add a proper error
message instead.
- Link to v1: https://lore.kernel.org/all/20260518082120.3890552-1-lihongfu@kylinos.cn/
--
2.25.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v10 1/6] selftests/mm: move pkey selftest helpers to pkey_util.c
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
@ 2026-07-06 8:15 ` Hongfu Li
2026-07-06 8:15 ` [PATCH v10 2/6] selftests/mm: unify pkey sighandler selftest assertions and tracing Hongfu Li
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-06 8:15 UTC (permalink / raw)
To: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah
Cc: jhubbard, joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li, Hongfu Li
Move pkey selftest debugging helpers into shared code so both pkey
selftests can use the same tracing and abort-hook logic. Also fix
cat_into_file() to print file, not str, in the open() failure message.
Signed-off-by: Hongfu Li <lihongfu@kylinos.cn>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Liam R. Howlett (Oracle) <liam@infradead.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Tested-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
tools/testing/selftests/mm/pkey-helpers.h | 4 +-
tools/testing/selftests/mm/pkey_util.c | 90 ++++++++++++++++++++
tools/testing/selftests/mm/protection_keys.c | 87 -------------------
3 files changed, 93 insertions(+), 88 deletions(-)
diff --git a/tools/testing/selftests/mm/pkey-helpers.h b/tools/testing/selftests/mm/pkey-helpers.h
index 2c377f4e9df1..46a8a1878dc1 100644
--- a/tools/testing/selftests/mm/pkey-helpers.h
+++ b/tools/testing/selftests/mm/pkey-helpers.h
@@ -68,7 +68,9 @@ static inline void sigsafe_printf(const char *format, ...)
#define dprintf3(args...) dprintf_level(3, args)
#define dprintf4(args...) dprintf_level(4, args)
-extern void abort_hooks(void);
+void tracing_on(void);
+void tracing_off(void);
+void abort_hooks(void);
#define pkey_assert(condition) do { \
if (!(condition)) { \
dprintf0("# assert() at %s::%d test_nr: %d iteration: %d\n", \
diff --git a/tools/testing/selftests/mm/pkey_util.c b/tools/testing/selftests/mm/pkey_util.c
index 255b332f7a08..fbef3cd45447 100644
--- a/tools/testing/selftests/mm/pkey_util.c
+++ b/tools/testing/selftests/mm/pkey_util.c
@@ -2,9 +2,99 @@
#define __SANE_USERSPACE_TYPES__
#include <sys/syscall.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
#include "pkey-helpers.h"
+int iteration_nr = 1;
+int test_nr;
+int dprint_in_signal;
+
+#if CONTROL_TRACING > 0
+static void cat_into_file(char *str, char *file)
+{
+ int fd = open(file, O_RDWR);
+ int ret;
+
+ dprintf2("%s(): writing '%s' to '%s'\n", __func__, str, file);
+ /*
+ * these need to be raw because they are called under
+ * pkey_assert()
+ */
+ if (fd < 0) {
+ fprintf(stderr, "error opening '%s'\n", file);
+ perror("error: ");
+ exit(__LINE__);
+ }
+
+ ret = write(fd, str, strlen(str));
+ if (ret != strlen(str)) {
+ perror("write to file failed");
+ fprintf(stderr, "filename: '%s' str: '%s'\n", file, str);
+ exit(__LINE__);
+ }
+ close(fd);
+}
+
+static int warned_tracing;
+static int tracing_root_ok(void)
+{
+ if (geteuid() != 0) {
+ if (!warned_tracing)
+ fprintf(stderr, "WARNING: not run as root, "
+ "can not do tracing control\n");
+ warned_tracing = 1;
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+void tracing_on(void)
+{
+#if CONTROL_TRACING > 0
+#define TRACEDIR "/sys/kernel/tracing"
+ char pidstr[32];
+
+ if (!tracing_root_ok())
+ return;
+
+ sprintf(pidstr, "%d", getpid());
+ cat_into_file("0", TRACEDIR "/tracing_on");
+ cat_into_file("\n", TRACEDIR "/trace");
+ if (1) {
+ cat_into_file("function_graph", TRACEDIR "/current_tracer");
+ cat_into_file("1", TRACEDIR "/options/funcgraph-proc");
+ } else {
+ cat_into_file("nop", TRACEDIR "/current_tracer");
+ }
+ cat_into_file(pidstr, TRACEDIR "/set_ftrace_pid");
+ cat_into_file("1", TRACEDIR "/tracing_on");
+ dprintf1("enabled tracing\n");
+#endif
+}
+
+void tracing_off(void)
+{
+#if CONTROL_TRACING > 0
+ if (!tracing_root_ok())
+ return;
+ cat_into_file("0", "/sys/kernel/tracing/tracing_on");
+#endif
+}
+
+void abort_hooks(void)
+{
+ fflush(stdout);
+ fprintf(stderr, "running %s()...\n", __func__);
+ tracing_off();
+#ifdef SLEEP_ON_ABORT
+ sleep(SLEEP_ON_ABORT);
+#endif
+}
+
int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
{
int ret = syscall(SYS_pkey_alloc, flags, init_val);
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index 9a6d954ee371..be4a0470cc61 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -49,11 +49,7 @@
#include "hugepage_settings.h"
#include "pkey-helpers.h"
-int iteration_nr = 1;
-int test_nr;
-
u64 shadow_pkey_reg;
-int dprint_in_signal;
noinline int read_ptr(int *ptr)
{
@@ -62,89 +58,6 @@ noinline int read_ptr(int *ptr)
return *ptr;
}
-#if CONTROL_TRACING > 0
-static void cat_into_file(char *str, char *file)
-{
- int fd = open(file, O_RDWR);
- int ret;
-
- dprintf2("%s(): writing '%s' to '%s'\n", __func__, str, file);
- /*
- * these need to be raw because they are called under
- * pkey_assert()
- */
- if (fd < 0) {
- fprintf(stderr, "error opening '%s'\n", str);
- perror("error: ");
- exit(__LINE__);
- }
-
- ret = write(fd, str, strlen(str));
- if (ret != strlen(str)) {
- perror("write to file failed");
- fprintf(stderr, "filename: '%s' str: '%s'\n", file, str);
- exit(__LINE__);
- }
- close(fd);
-}
-
-static int warned_tracing;
-static int tracing_root_ok(void)
-{
- if (geteuid() != 0) {
- if (!warned_tracing)
- fprintf(stderr, "WARNING: not run as root, "
- "can not do tracing control\n");
- warned_tracing = 1;
- return 0;
- }
- return 1;
-}
-#endif
-
-static void tracing_on(void)
-{
-#if CONTROL_TRACING > 0
-#define TRACEDIR "/sys/kernel/tracing"
- char pidstr[32];
-
- if (!tracing_root_ok())
- return;
-
- sprintf(pidstr, "%d", getpid());
- cat_into_file("0", TRACEDIR "/tracing_on");
- cat_into_file("\n", TRACEDIR "/trace");
- if (1) {
- cat_into_file("function_graph", TRACEDIR "/current_tracer");
- cat_into_file("1", TRACEDIR "/options/funcgraph-proc");
- } else {
- cat_into_file("nop", TRACEDIR "/current_tracer");
- }
- cat_into_file(pidstr, TRACEDIR "/set_ftrace_pid");
- cat_into_file("1", TRACEDIR "/tracing_on");
- dprintf1("enabled tracing\n");
-#endif
-}
-
-static void tracing_off(void)
-{
-#if CONTROL_TRACING > 0
- if (!tracing_root_ok())
- return;
- cat_into_file("0", "/sys/kernel/tracing/tracing_on");
-#endif
-}
-
-void abort_hooks(void)
-{
- fflush(stdout);
- fprintf(stderr, "running %s()...\n", __func__);
- tracing_off();
-#ifdef SLEEP_ON_ABORT
- sleep(SLEEP_ON_ABORT);
-#endif
-}
-
/*
* This attempts to have roughly a page of instructions followed by a few
* instructions that do a write, and another page of instructions. That
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v10 2/6] selftests/mm: unify pkey sighandler selftest assertions and tracing
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
2026-07-06 8:15 ` [PATCH v10 1/6] selftests/mm: move pkey selftest helpers to pkey_util.c Hongfu Li
@ 2026-07-06 8:15 ` Hongfu Li
2026-07-06 8:15 ` [PATCH v10 3/6] selftests/mm: use pkey_assert on clone_raw failure in pkey test Hongfu Li
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-06 8:15 UTC (permalink / raw)
To: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah
Cc: jhubbard, joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li, Hongfu Li
Add per-test tracing to the pkey signal-handler selftest and use
pkey_assert() for error handling. Each test enables tracing at start
and disables it at end; on failure, pkey_assert() calls abort_hooks()
to turn tracing off so ftrace is not left enabled.
Signed-off-by: Hongfu Li <lihongfu@kylinos.cn>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Liam R. Howlett (Oracle) <liam@infradead.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Tested-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
.../selftests/mm/pkey_sighandler_tests.c | 89 +++++++++----------
1 file changed, 44 insertions(+), 45 deletions(-)
diff --git a/tools/testing/selftests/mm/pkey_sighandler_tests.c b/tools/testing/selftests/mm/pkey_sighandler_tests.c
index 302fef54049c..8b3400379423 100644
--- a/tools/testing/selftests/mm/pkey_sighandler_tests.c
+++ b/tools/testing/selftests/mm/pkey_sighandler_tests.c
@@ -19,7 +19,6 @@
#include <stdint.h>
#include <stdbool.h>
#include <signal.h>
-#include <assert.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
@@ -207,15 +206,14 @@ static void test_sigsegv_handler_with_pkey0_disabled(void)
struct sigaction sa;
pthread_attr_t attr;
pthread_t thr;
+ int ret;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sigsegv_handler;
sigemptyset(&sa.sa_mask);
- if (sigaction(SIGSEGV, &sa, NULL) == -1) {
- perror("sigaction");
- exit(EXIT_FAILURE);
- }
+ ret = sigaction(SIGSEGV, &sa, NULL);
+ pkey_assert(ret == 0);
memset(&siginfo, 0, sizeof(siginfo));
@@ -247,15 +245,14 @@ static void test_sigsegv_handler_cannot_access_stack(void)
struct sigaction sa;
pthread_attr_t attr;
pthread_t thr;
+ int ret;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sigsegv_handler;
sigemptyset(&sa.sa_mask);
- if (sigaction(SIGSEGV, &sa, NULL) == -1) {
- perror("sigaction");
- exit(EXIT_FAILURE);
- }
+ ret = sigaction(SIGSEGV, &sa, NULL);
+ pkey_assert(ret == 0);
memset(&siginfo, 0, sizeof(siginfo));
@@ -288,21 +285,20 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
int parent_pid = 0;
int child_pid = 0;
u64 pkey_reg;
+ long ret;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
sa.sa_sigaction = sigsegv_handler;
sigemptyset(&sa.sa_mask);
- if (sigaction(SIGSEGV, &sa, NULL) == -1) {
- perror("sigaction");
- exit(EXIT_FAILURE);
- }
+ ret = sigaction(SIGSEGV, &sa, NULL);
+ pkey_assert(ret == 0);
stack = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- assert(stack != MAP_FAILED);
+ pkey_assert(stack != MAP_FAILED);
/* Allow access to MPK 0 and MPK 1 */
pkey_reg = pkey_reg_restrictive_default();
@@ -323,13 +319,13 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
memset(&siginfo, 0, sizeof(siginfo));
/* Use clone to avoid newer glibcs using rseq on new threads */
- long ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
- CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
- CLONE_DETACHED,
- stack + STACK_SIZE,
- &parent_pid,
- &child_pid);
+ ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
+ CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
+ CLONE_DETACHED,
+ stack + STACK_SIZE,
+ &parent_pid,
+ &child_pid);
if (ret < 0) {
errno = -ret;
@@ -358,6 +354,7 @@ static void test_pkru_preserved_after_sigusr1(void)
{
struct sigaction sa;
u64 pkey_reg;
+ int ret;
/* Allow access to MPK 0 and an arbitrary set of keys */
pkey_reg = pkey_reg_restrictive_default();
@@ -369,10 +366,8 @@ static void test_pkru_preserved_after_sigusr1(void)
sa.sa_sigaction = sigusr1_handler;
sigemptyset(&sa.sa_mask);
- if (sigaction(SIGUSR1, &sa, NULL) == -1) {
- perror("sigaction");
- exit(EXIT_FAILURE);
- }
+ ret = sigaction(SIGUSR1, &sa, NULL);
+ pkey_assert(ret == 0);
memset(&siginfo, 0, sizeof(siginfo));
@@ -444,6 +439,13 @@ static void test_pkru_sigreturn(void)
int parent_pid = 0;
int child_pid = 0;
u64 pkey_reg;
+ long ret;
+
+ /*
+ * SIGSEGV handler is reset to SIG_DFL below; turn tracing off first
+ * so a crash does not leave ftrace enabled.
+ */
+ tracing_off();
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
@@ -453,24 +455,20 @@ static void test_pkru_sigreturn(void)
* For this testcase, we do not want to handle SIGSEGV. Reset handler
* to default so that the application can crash if it receives SIGSEGV.
*/
- if (sigaction(SIGSEGV, &sa, NULL) == -1) {
- perror("sigaction");
- exit(EXIT_FAILURE);
- }
+ ret = sigaction(SIGSEGV, &sa, NULL);
+ pkey_assert(ret == 0);
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
sa.sa_sigaction = sigusr2_handler;
sigemptyset(&sa.sa_mask);
- if (sigaction(SIGUSR2, &sa, NULL) == -1) {
- perror("sigaction");
- exit(EXIT_FAILURE);
- }
+ ret = sigaction(SIGUSR2, &sa, NULL);
+ pkey_assert(ret == 0);
stack = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- assert(stack != MAP_FAILED);
+ pkey_assert(stack != MAP_FAILED);
/*
* Allow access to MPK 0 and MPK 2. The child thread (to be created
@@ -494,13 +492,13 @@ static void test_pkru_sigreturn(void)
sigstack.ss_size = STACK_SIZE;
/* Use clone to avoid newer glibcs using rseq on new threads */
- long ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
- CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
- CLONE_DETACHED,
- stack + STACK_SIZE,
- &parent_pid,
- &child_pid);
+ ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
+ CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
+ CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
+ CLONE_DETACHED,
+ stack + STACK_SIZE,
+ &parent_pid,
+ &child_pid);
if (ret < 0) {
errno = -ret;
@@ -530,16 +528,17 @@ static void (*pkey_tests[])(void) = {
int main(int argc, char *argv[])
{
- int i;
-
ksft_print_header();
ksft_set_plan(ARRAY_SIZE(pkey_tests));
if (!is_pkeys_supported())
ksft_exit_skip("pkeys not supported\n");
- for (i = 0; i < ARRAY_SIZE(pkey_tests); i++)
- (*pkey_tests[i])();
+ for (test_nr = 0; test_nr < ARRAY_SIZE(pkey_tests); test_nr++) {
+ tracing_on();
+ (*pkey_tests[test_nr])();
+ tracing_off();
+ }
ksft_finished();
return 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v10 3/6] selftests/mm: use pkey_assert on clone_raw failure in pkey test
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
2026-07-06 8:15 ` [PATCH v10 1/6] selftests/mm: move pkey selftest helpers to pkey_util.c Hongfu Li
2026-07-06 8:15 ` [PATCH v10 2/6] selftests/mm: unify pkey sighandler selftest assertions and tracing Hongfu Li
@ 2026-07-06 8:15 ` Hongfu Li
2026-07-06 8:15 ` [PATCH v10 4/6] selftests/mm: add missing mmap() return checks in pkey tests Hongfu Li
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-06 8:15 UTC (permalink / raw)
To: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah
Cc: jhubbard, joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li, Hongfu Li
Use pkey_assert(0) instead of perror("clone") when clone_raw() fails.
The old path only printed an error and continued; the test now exits
via pkey_assert() on failure so it does not hang or proceed with an
invalid child.
Signed-off-by: Hongfu Li <lihongfu@kylinos.cn>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Liam R. Howlett (Oracle) <liam@infradead.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Tested-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
tools/testing/selftests/mm/pkey_sighandler_tests.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/mm/pkey_sighandler_tests.c b/tools/testing/selftests/mm/pkey_sighandler_tests.c
index 8b3400379423..188513e94fc5 100644
--- a/tools/testing/selftests/mm/pkey_sighandler_tests.c
+++ b/tools/testing/selftests/mm/pkey_sighandler_tests.c
@@ -329,7 +329,7 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
if (ret < 0) {
errno = -ret;
- perror("clone");
+ pkey_assert(0);
} else if (ret == 0) {
thread_segv_maperr_ptr(&sigstack);
syscall_raw(SYS_exit, 0, 0, 0, 0, 0, 0);
@@ -502,7 +502,7 @@ static void test_pkru_sigreturn(void)
if (ret < 0) {
errno = -ret;
- perror("clone");
+ pkey_assert(0);
} else if (ret == 0) {
thread_sigusr2_self(&sigstack);
syscall_raw(SYS_exit, 0, 0, 0, 0, 0, 0);
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v10 4/6] selftests/mm: add missing mmap() return checks in pkey tests
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
` (2 preceding siblings ...)
2026-07-06 8:15 ` [PATCH v10 3/6] selftests/mm: use pkey_assert on clone_raw failure in pkey test Hongfu Li
@ 2026-07-06 8:15 ` Hongfu Li
2026-07-06 8:15 ` [PATCH v10 5/6] selftests/mm: add missing pthread_create() " Hongfu Li
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-06 8:15 UTC (permalink / raw)
To: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah
Cc: jhubbard, joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li, Hongfu Li
Add missing checks against mmap() return value, replace (void *)-1
with MAP_FAILED for better readability and consistency.
Signed-off-by: Hongfu Li <lihongfu@kylinos.cn>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Liam R. Howlett (Oracle) <liam@infradead.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Tested-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
tools/testing/selftests/mm/pkey-powerpc.h | 2 +-
tools/testing/selftests/mm/pkey_sighandler_tests.c | 2 ++
tools/testing/selftests/mm/protection_keys.c | 12 +++++++-----
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/mm/pkey-powerpc.h b/tools/testing/selftests/mm/pkey-powerpc.h
index 17bf2d1b0192..2ce85580b404 100644
--- a/tools/testing/selftests/mm/pkey-powerpc.h
+++ b/tools/testing/selftests/mm/pkey-powerpc.h
@@ -126,7 +126,7 @@ static inline void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 p
size, prot, pkey);
pkey_assert(pkey < NR_PKEYS);
ptr = mmap(NULL, size, prot, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- pkey_assert(ptr != (void *)-1);
+ pkey_assert(ptr != MAP_FAILED);
ret = syscall(__NR_subpage_prot, ptr, size, NULL);
if (ret) {
diff --git a/tools/testing/selftests/mm/pkey_sighandler_tests.c b/tools/testing/selftests/mm/pkey_sighandler_tests.c
index 188513e94fc5..8f98e6d9349f 100644
--- a/tools/testing/selftests/mm/pkey_sighandler_tests.c
+++ b/tools/testing/selftests/mm/pkey_sighandler_tests.c
@@ -313,6 +313,7 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
/* Set up alternate signal stack that will use the default MPK */
sigstack.ss_sp = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ pkey_assert(sigstack.ss_sp != MAP_FAILED);
sigstack.ss_flags = 0;
sigstack.ss_size = STACK_SIZE;
@@ -488,6 +489,7 @@ static void test_pkru_sigreturn(void)
/* Set up alternate signal stack that will use the default MPK */
sigstack.ss_sp = mmap(0, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ pkey_assert(sigstack.ss_sp != MAP_FAILED);
sigstack.ss_flags = 0;
sigstack.ss_size = STACK_SIZE;
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index be4a0470cc61..ae6e1530b354 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -582,7 +582,7 @@ static void *malloc_pkey_with_mprotect(long size, int prot, u16 pkey)
size, prot, pkey);
pkey_assert(pkey < NR_PKEYS);
ptr = mmap(NULL, size, prot, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- pkey_assert(ptr != (void *)-1);
+ pkey_assert(ptr != MAP_FAILED);
ret = mprotect_pkey((void *)ptr, PAGE_SIZE, prot, pkey);
pkey_assert(!ret);
record_pkey_malloc(ptr, size, prot);
@@ -605,7 +605,7 @@ static void *malloc_pkey_anon_huge(long size, int prot, u16 pkey)
*/
size = ALIGN_UP(size, HPAGE_SIZE * 2);
ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- pkey_assert(ptr != (void *)-1);
+ pkey_assert(ptr != MAP_FAILED);
record_pkey_malloc(ptr, size, prot);
mprotect_pkey(ptr, size, prot, pkey);
@@ -663,7 +663,7 @@ static void *malloc_pkey_hugetlb(long size, int prot, u16 pkey)
size = ALIGN_UP(size, HPAGE_SIZE * 2);
pkey_assert(pkey < NR_PKEYS);
ptr = mmap(NULL, size, PROT_NONE, flags, -1, 0);
- pkey_assert(ptr != (void *)-1);
+ pkey_assert(ptr != MAP_FAILED);
mprotect_pkey(ptr, size, prot, pkey);
record_pkey_malloc(ptr, size, prot);
@@ -692,7 +692,7 @@ static void *malloc_pkey(long size, int prot, u16 pkey)
pkey_assert(malloc_type < nr_malloc_types);
ret = pkey_malloc[malloc_type](size, prot, pkey);
- pkey_assert(ret != (void *)-1);
+ pkey_assert(ret != MAP_FAILED);
malloc_type++;
if (malloc_type >= nr_malloc_types)
@@ -1110,6 +1110,7 @@ static void arch_force_pkey_reg_init(void)
* doing the XSAVE size enumeration dance.
*/
buf = mmap(NULL, 1*MB, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ pkey_assert(buf != MAP_FAILED);
/* These __builtins require compiling with -mxsave */
@@ -1676,7 +1677,8 @@ int main(void)
ksft_print_msg("running PKEY tests for unsupported CPU/OS\n");
ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- assert(ptr != (void *)-1);
+ if (ptr == MAP_FAILED)
+ ksft_exit_fail_perror("mmap");
test_mprotect_pkey_on_unsupported_cpu(ptr, 1);
ksft_test_result_pass("pkey on unsupported CPU/OS\n");
ksft_finished();
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v10 5/6] selftests/mm: add missing pthread_create() return checks in pkey tests
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
` (3 preceding siblings ...)
2026-07-06 8:15 ` [PATCH v10 4/6] selftests/mm: add missing mmap() return checks in pkey tests Hongfu Li
@ 2026-07-06 8:15 ` Hongfu Li
2026-07-06 8:16 ` [PATCH v10 6/6] selftests/mm: fix clone cleartid race in pkey sighandler tests Hongfu Li
2026-07-06 23:28 ` [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Andrew Morton
6 siblings, 0 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-06 8:15 UTC (permalink / raw)
To: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah
Cc: jhubbard, joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li, Hongfu Li
Add missing pthread_create() return checks in pkey sighandler tests
to avoid hanging in pthread_cond_wait() when thread creation fails.
Signed-off-by: Hongfu Li <lihongfu@kylinos.cn>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Liam R. Howlett (Oracle) <liam@infradead.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Tested-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
tools/testing/selftests/mm/pkey_sighandler_tests.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/mm/pkey_sighandler_tests.c b/tools/testing/selftests/mm/pkey_sighandler_tests.c
index 8f98e6d9349f..cbc24d6cf770 100644
--- a/tools/testing/selftests/mm/pkey_sighandler_tests.c
+++ b/tools/testing/selftests/mm/pkey_sighandler_tests.c
@@ -220,7 +220,11 @@ static void test_sigsegv_handler_with_pkey0_disabled(void)
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_create(&thr, &attr, thread_segv_with_pkey0_disabled, NULL);
+ ret = pthread_create(&thr, &attr, thread_segv_with_pkey0_disabled, NULL);
+ if (ret) {
+ errno = ret;
+ pkey_assert(0);
+ }
pthread_mutex_lock(&mutex);
while (siginfo.si_signo == 0)
@@ -259,7 +263,11 @@ static void test_sigsegv_handler_cannot_access_stack(void)
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_create(&thr, &attr, thread_segv_pkuerr_stack, NULL);
+ ret = pthread_create(&thr, &attr, thread_segv_pkuerr_stack, NULL);
+ if (ret) {
+ errno = ret;
+ pkey_assert(0);
+ }
pthread_mutex_lock(&mutex);
while (siginfo.si_signo == 0)
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v10 6/6] selftests/mm: fix clone cleartid race in pkey sighandler tests
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
` (4 preceding siblings ...)
2026-07-06 8:15 ` [PATCH v10 5/6] selftests/mm: add missing pthread_create() " Hongfu Li
@ 2026-07-06 8:16 ` Hongfu Li
2026-07-06 23:28 ` [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Andrew Morton
6 siblings, 0 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-06 8:16 UTC (permalink / raw)
To: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah
Cc: jhubbard, joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li, Hongfu Li
Passing a stack-local child_pid to clone() with CLONE_CHILD_CLEARTID is
unsafe: the kernel clears that address when the child exits, which may
happen after the test function has returned and the stack slot has been
reused.
Neither testcase uses the settid/cleartid pointers for synchronization.
Drop CLONE_PARENT_SETTID and CLONE_CHILD_CLEARTID and pass NULL for the
clone tid arguments. Wait for the clone child to exit via tkill in
test_sigsegv_handler_with_different_pkey_for_stack(), matching
test_pkru_sigreturn(), so the detached thread cannot overlap with the
next testcase.
Signed-off-by: Hongfu Li <lihongfu@kylinos.cn>
---
.../selftests/mm/pkey_sighandler_tests.c | 20 +++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/mm/pkey_sighandler_tests.c b/tools/testing/selftests/mm/pkey_sighandler_tests.c
index cbc24d6cf770..c218d0510a2a 100644
--- a/tools/testing/selftests/mm/pkey_sighandler_tests.c
+++ b/tools/testing/selftests/mm/pkey_sighandler_tests.c
@@ -290,7 +290,6 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
static stack_t sigstack;
void *stack;
int pkey;
- int parent_pid = 0;
int child_pid = 0;
u64 pkey_reg;
long ret;
@@ -330,11 +329,10 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
/* Use clone to avoid newer glibcs using rseq on new threads */
ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
CLONE_DETACHED,
stack + STACK_SIZE,
- &parent_pid,
- &child_pid);
+ NULL,
+ NULL);
if (ret < 0) {
errno = -ret;
@@ -344,11 +342,19 @@ static void test_sigsegv_handler_with_different_pkey_for_stack(void)
syscall_raw(SYS_exit, 0, 0, 0, 0, 0, 0);
}
+ child_pid = ret;
+
pthread_mutex_lock(&mutex);
while (siginfo.si_signo == 0)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
+ /* Wait for child to exit before returning */
+ do {
+ sched_yield();
+ ret = syscall_raw(SYS_tkill, child_pid, 0, 0, 0, 0, 0);
+ } while (ret != -ESRCH && ret != -EINVAL);
+
ksft_test_result(siginfo.si_signo == SIGSEGV &&
siginfo.si_code == SEGV_MAPERR &&
siginfo.si_addr == NULL,
@@ -445,7 +451,6 @@ static void test_pkru_sigreturn(void)
static stack_t sigstack;
void *stack;
int pkey;
- int parent_pid = 0;
int child_pid = 0;
u64 pkey_reg;
long ret;
@@ -504,11 +509,10 @@ static void test_pkru_sigreturn(void)
/* Use clone to avoid newer glibcs using rseq on new threads */
ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
CLONE_DETACHED,
stack + STACK_SIZE,
- &parent_pid,
- &child_pid);
+ NULL,
+ NULL);
if (ret < 0) {
errno = -ret;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
` (5 preceding siblings ...)
2026-07-06 8:16 ` [PATCH v10 6/6] selftests/mm: fix clone cleartid race in pkey sighandler tests Hongfu Li
@ 2026-07-06 23:28 ` Andrew Morton
2026-07-07 3:25 ` Hongfu Li
6 siblings, 1 reply; 9+ messages in thread
From: Andrew Morton @ 2026-07-06 23:28 UTC (permalink / raw)
To: Hongfu Li
Cc: david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah, jhubbard,
joey.gouly, keith.lucas, kevin.brodsky, usama.anjum,
yury.khrustalev, zwisler, linux-mm, linux-kselftest, linux-kernel,
hongfu.li
On Mon, 6 Jul 2026 16:15:54 +0800 Hongfu Li <lihongfu@kylinos.cn> wrote:
> The main changes in this series are to refactor shared tracing and assertion
> helpers into a common file, unify both pkey selftests on pkey_assert() and
> per-test tracing for consistent diagnostics, and add missing mmap() return
> checks with MAP_FAILED used throughout for readability and consistency.
Thanks, I've updated mm.git to this version.
> v10:
> - Add patch 6/6 to fix a pre-existing cleartid race: remove unused
> settid/cleartid clone flags and wait for the clone child to exit in
> the sigsegv test.
Below is how v10 altered mm.git. As you mentioned, this is all from
the addition of [patch 6/6].
btw, I thought the official way to wait for a child thread to exit is
pthread_join()? Why is that sched_yield() loop used?
tools/testing/selftests/mm/pkey_sighandler_tests.c | 20 ++++++-----
1 file changed, 12 insertions(+), 8 deletions(-)
--- a/tools/testing/selftests/mm/pkey_sighandler_tests.c~b
+++ a/tools/testing/selftests/mm/pkey_sighandler_tests.c
@@ -290,7 +290,6 @@ static void test_sigsegv_handler_with_di
static stack_t sigstack;
void *stack;
int pkey;
- int parent_pid = 0;
int child_pid = 0;
u64 pkey_reg;
long ret;
@@ -330,11 +329,10 @@ static void test_sigsegv_handler_with_di
/* Use clone to avoid newer glibcs using rseq on new threads */
ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
CLONE_DETACHED,
stack + STACK_SIZE,
- &parent_pid,
- &child_pid);
+ NULL,
+ NULL);
if (ret < 0) {
errno = -ret;
@@ -344,11 +342,19 @@ static void test_sigsegv_handler_with_di
syscall_raw(SYS_exit, 0, 0, 0, 0, 0, 0);
}
+ child_pid = ret;
+
pthread_mutex_lock(&mutex);
while (siginfo.si_signo == 0)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
+ /* Wait for child to exit before returning */
+ do {
+ sched_yield();
+ ret = syscall_raw(SYS_tkill, child_pid, 0, 0, 0, 0, 0);
+ } while (ret != -ESRCH && ret != -EINVAL);
+
ksft_test_result(siginfo.si_signo == SIGSEGV &&
siginfo.si_code == SEGV_MAPERR &&
siginfo.si_addr == NULL,
@@ -445,7 +451,6 @@ static void test_pkru_sigreturn(void)
static stack_t sigstack;
void *stack;
int pkey;
- int parent_pid = 0;
int child_pid = 0;
u64 pkey_reg;
long ret;
@@ -504,11 +509,10 @@ static void test_pkru_sigreturn(void)
/* Use clone to avoid newer glibcs using rseq on new threads */
ret = clone_raw(CLONE_VM | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
- CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
CLONE_DETACHED,
stack + STACK_SIZE,
- &parent_pid,
- &child_pid);
+ NULL,
+ NULL);
if (ret < 0) {
errno = -ret;
_
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling
2026-07-06 23:28 ` [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Andrew Morton
@ 2026-07-07 3:25 ` Hongfu Li
0 siblings, 0 replies; 9+ messages in thread
From: Hongfu Li @ 2026-07-07 3:25 UTC (permalink / raw)
To: akpm
Cc: david, hongfu.li, jhubbard, joey.gouly, keith.lucas,
kevin.brodsky, liam, lihongfu, linux-kernel, linux-kselftest,
linux-mm, ljs, mhocko, rppt, shuah, surenb, usama.anjum, vbabka,
yury.khrustalev, zwisler
Hi,
> > The main changes in this series are to refactor shared tracing and assertion
> > helpers into a common file, unify both pkey selftests on pkey_assert() and
> > per-test tracing for consistent diagnostics, and add missing mmap() return
> > checks with MAP_FAILED used throughout for readability and consistency.
>
> Thanks, I've updated mm.git to this version.
>
> > v10:
> > - Add patch 6/6 to fix a pre-existing cleartid race: remove unused
> > settid/cleartid clone flags and wait for the clone child to exit in
> > the sigsegv test.
>
> Below is how v10 altered mm.git. As you mentioned, this is all from
> the addition of [patch 6/6].
>
> btw, I thought the official way to wait for a child thread to exit is
> pthread_join()? Why is that sched_yield() loop used?
Thanks a lot for your question.
As I understand it, the primary reason is pthread_create automatically
enables rseq on all threads, which corrupts the isolated pkey signal
handling kernel context this selftest is designed to exercise. We use
raw clone_raw explicitly to avoid rseq interference as noted in the
code comment.
Besides, pthread_join cannot work here. Since the thread is created via
raw clone instead of pthread_create, it is not tracked by libpthread at
all, so invoking pthread_join with its TID will return EINVAL.
Best regards,
Hongfu
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-07-07 3:25 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 8:15 [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Hongfu Li
2026-07-06 8:15 ` [PATCH v10 1/6] selftests/mm: move pkey selftest helpers to pkey_util.c Hongfu Li
2026-07-06 8:15 ` [PATCH v10 2/6] selftests/mm: unify pkey sighandler selftest assertions and tracing Hongfu Li
2026-07-06 8:15 ` [PATCH v10 3/6] selftests/mm: use pkey_assert on clone_raw failure in pkey test Hongfu Li
2026-07-06 8:15 ` [PATCH v10 4/6] selftests/mm: add missing mmap() return checks in pkey tests Hongfu Li
2026-07-06 8:15 ` [PATCH v10 5/6] selftests/mm: add missing pthread_create() " Hongfu Li
2026-07-06 8:16 ` [PATCH v10 6/6] selftests/mm: fix clone cleartid race in pkey sighandler tests Hongfu Li
2026-07-06 23:28 ` [PATCH v10 0/6] selftests/mm: refactor pkey helpers and fix mmap error handling Andrew Morton
2026-07-07 3:25 ` Hongfu Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox