mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures
@ 2026-04-07 14:35 Ricardo B. Marlière
  2026-04-07 14:35 ` [PATCH 1/3] selftests/namespaces: Kill grandchild in nsid fixture teardown Ricardo B. Marlière
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ricardo B. Marlière @ 2026-04-07 14:35 UTC (permalink / raw)
  To: Shuah Khan, Christian Brauner
  Cc: linux-kselftest, linux-kernel, Ricardo B. Marliere

This series addresses three reliability problems in the namespaces selftest
suite that cause tests to hang or report incorrect results.

The first patch fixes a hang in nsid_test where the grandchild process is
not reaped during fixture teardown, leaving it alive and holding the TAP
pipe write-end open so the test runner blocks indefinitely waiting for EOF.

The second and third patches fix two problems in listns_efault_test: a
waitpid(-1) race that can cause the iterator child to be consumed during
namespace cleanup (leading to an indefinite block on the subsequent targeted
waitpid), and a false FAIL verdict on kernels that do not implement listns()
(the EFAULT tests should SKIP in that case, consistent with every other
listns test that already handles ENOSYS correctly).

Assisted-by: Claude Sonnet 4.6
Signed-off-by: Ricardo B. Marliere <rbm@suse.com>
---
Ricardo B. Marlière (3):
      selftests/namespaces: Kill grandchild in nsid fixture teardown
      selftests/namespaces: Fix waitpid race in listns_efault_test cleanup
      selftests/namespaces: Skip efault tests when listns() is not available

 .../selftests/namespaces/listns_efault_test.c      | 33 ++++++++++++++++++----
 tools/testing/selftests/namespaces/nsid_test.c     | 14 ++++++++-
 2 files changed, 40 insertions(+), 7 deletions(-)
---
base-commit: bfe62a454542cfad3379f6ef5680b125f41e20f4
change-id: 20260407-selftests-namespaces_fixes-43ff47179e5c

Best regards,
--  
Ricardo B. Marlière <rbm@suse.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] selftests/namespaces: Kill grandchild in nsid fixture teardown
  2026-04-07 14:35 [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Ricardo B. Marlière
@ 2026-04-07 14:35 ` Ricardo B. Marlière
  2026-04-07 14:35 ` [PATCH 2/3] selftests/namespaces: Fix waitpid race in listns_efault_test cleanup Ricardo B. Marlière
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ricardo B. Marlière @ 2026-04-07 14:35 UTC (permalink / raw)
  To: Shuah Khan, Christian Brauner
  Cc: linux-kselftest, linux-kernel, Ricardo B. Marliere

The timens_separate and pidns_separate test cases fork a grandchild that
calls pause().  FIXTURE_TEARDOWN only kills the direct child, which is the
init process of the grandchild's namespace.  Once the child (init) exits,
the grandchild is reparented to the host init but remains alive and
continues to hold the inherited write end of the test runner's TAP pipe
open.  tap_prefix never receives EOF and blocks indefinitely, hanging the
entire test collection.

Record the grandchild PID in the fixture struct so that teardown can send
SIGKILL and reap it before dealing with the child.  The grandchild must be
reaped first because the child acts as its PID namespace init; killing the
child first would kill the grandchild without giving us a chance to
waitpid() it.

Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
 tools/testing/selftests/namespaces/nsid_test.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/namespaces/nsid_test.c b/tools/testing/selftests/namespaces/nsid_test.c
index b4a14c6693a5..46dc838cba82 100644
--- a/tools/testing/selftests/namespaces/nsid_test.c
+++ b/tools/testing/selftests/namespaces/nsid_test.c
@@ -25,14 +25,24 @@
 /* Fixture for tests that create child processes */
 FIXTURE(nsid) {
 	pid_t child_pid;
+	pid_t grandchild_pid;
 };
 
 FIXTURE_SETUP(nsid) {
 	self->child_pid = 0;
+	self->grandchild_pid = 0;
 }
 
 FIXTURE_TEARDOWN(nsid) {
-	/* Clean up any child process that may still be running */
+	/*
+	 * Kill grandchild first: timens_separate and pidns_separate fork a
+	 * grandchild that calls pause().  It is reparented to init on child
+	 * exit and keeps the test runner's tap pipe open, hanging the runner.
+	 */
+	if (self->grandchild_pid > 0) {
+		kill(self->grandchild_pid, SIGKILL);
+		waitpid(self->grandchild_pid, NULL, 0);
+	}
 	if (self->child_pid > 0) {
 		kill(self->child_pid, SIGKILL);
 		waitpid(self->child_pid, NULL, 0);
@@ -676,6 +686,7 @@ TEST_F(nsid, timens_separate)
 
 	pid_t grandchild_pid;
 	ASSERT_EQ(read(pipefd[0], &grandchild_pid, sizeof(grandchild_pid)), sizeof(grandchild_pid));
+	self->grandchild_pid = grandchild_pid;
 	close(pipefd[0]);
 
 	/* Open grandchild's time namespace */
@@ -797,6 +808,7 @@ TEST_F(nsid, pidns_separate)
 
 	pid_t grandchild_pid;
 	ASSERT_EQ(read(pipefd[0], &grandchild_pid, sizeof(grandchild_pid)), sizeof(grandchild_pid));
+	self->grandchild_pid = grandchild_pid;
 	close(pipefd[0]);
 
 	/* Open grandchild's PID namespace */

-- 
2.53.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/3] selftests/namespaces: Fix waitpid race in listns_efault_test cleanup
  2026-04-07 14:35 [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Ricardo B. Marlière
  2026-04-07 14:35 ` [PATCH 1/3] selftests/namespaces: Kill grandchild in nsid fixture teardown Ricardo B. Marlière
@ 2026-04-07 14:35 ` Ricardo B. Marlière
  2026-04-07 14:35 ` [PATCH 3/3] selftests/namespaces: Skip efault tests when listns() is not available Ricardo B. Marlière
  2026-04-09 13:06 ` [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Christian Brauner
  3 siblings, 0 replies; 5+ messages in thread
From: Ricardo B. Marlière @ 2026-04-07 14:35 UTC (permalink / raw)
  To: Shuah Khan, Christian Brauner
  Cc: linux-kselftest, linux-kernel, Ricardo B. Marliere

The efault tests spawn two categories of child processes: namespace
children (each in its own mount namespace, for concurrent destruction) and
an iterator child that calls listns() in a tight loop.  The cleanup loop
used waitpid(-1), which reaps any child in any order. If the iterator child
exits early (e.g. because listns() returned ENOSYS) before all namespace
children have been reaped, waitpid(-1) may consume it instead.  The
subsequent targeted waitpid(iter_pid) would then block indefinitely.

Track the PIDs of the namespace children explicitly and use targeted
waitpid() calls in the cleanup loop so the iterator child cannot be
inadvertently reaped during namespace cleanup.

Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
 tools/testing/selftests/namespaces/listns_efault_test.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/namespaces/listns_efault_test.c b/tools/testing/selftests/namespaces/listns_efault_test.c
index c7ed4023d7a8..ac3b208264f5 100644
--- a/tools/testing/selftests/namespaces/listns_efault_test.c
+++ b/tools/testing/selftests/namespaces/listns_efault_test.c
@@ -39,7 +39,7 @@ TEST(listns_partial_fault_with_ns_cleanup)
 	__u64 *ns_ids;
 	ssize_t ret;
 	long page_size;
-	pid_t pid, iter_pid;
+	pid_t pid, iter_pid, ns_pids[5];
 	int pidfds[5];
 	int sv[5][2];
 	int iter_pidfd;
@@ -115,6 +115,7 @@ TEST(listns_partial_fault_with_ns_cleanup)
 
 		pid = create_child(&pidfds[i], CLONE_NEWNS);
 		ASSERT_NE(pid, -1);
+		ns_pids[i] = pid;
 
 		if (pid == 0) {
 			close(sv[i][0]); /* Close parent end */
@@ -165,7 +166,7 @@ TEST(listns_partial_fault_with_ns_cleanup)
 
 	/* Wait for all mount namespace children to exit and cleanup */
 	for (i = 0; i < 5; i++) {
-		waitpid(-1, NULL, 0);
+		waitpid(ns_pids[i], NULL, 0);
 		close(sv[i][0]);
 		close(pidfds[i]);
 	}
@@ -251,7 +252,7 @@ TEST(listns_late_fault_with_ns_cleanup)
 	__u64 *ns_ids;
 	ssize_t ret;
 	long page_size;
-	pid_t pid, iter_pid;
+	pid_t pid, iter_pid, ns_pids[10];
 	int pidfds[10];
 	int sv[10][2];
 	int iter_pidfd;
@@ -321,6 +322,7 @@ TEST(listns_late_fault_with_ns_cleanup)
 
 		pid = create_child(&pidfds[i], CLONE_NEWNS);
 		ASSERT_NE(pid, -1);
+		ns_pids[i] = pid;
 
 		if (pid == 0) {
 			close(sv[i][0]); /* Close parent end */
@@ -374,7 +376,7 @@ TEST(listns_late_fault_with_ns_cleanup)
 
 	/* Wait for all children and cleanup */
 	for (i = 0; i < 10; i++) {
-		waitpid(-1, NULL, 0);
+		waitpid(ns_pids[i], NULL, 0);
 		close(sv[i][0]);
 		close(pidfds[i]);
 	}
@@ -403,7 +405,7 @@ TEST(listns_mnt_ns_cleanup_on_fault)
 	__u64 *ns_ids;
 	ssize_t ret;
 	long page_size;
-	pid_t pid, iter_pid;
+	pid_t pid, iter_pid, ns_pids[8];
 	int pidfds[8];
 	int sv[8][2];
 	int iter_pidfd;
@@ -463,6 +465,7 @@ TEST(listns_mnt_ns_cleanup_on_fault)
 
 		pid = create_child(&pidfds[i], CLONE_NEWNS);
 		ASSERT_NE(pid, -1);
+		ns_pids[i] = pid;
 
 		if (pid == 0) {
 			close(sv[i][0]); /* Close parent end */
@@ -509,7 +512,7 @@ TEST(listns_mnt_ns_cleanup_on_fault)
 
 	/* Wait for children and cleanup */
 	for (i = 0; i < 8; i++) {
-		waitpid(-1, NULL, 0);
+		waitpid(ns_pids[i], NULL, 0);
 		close(sv[i][0]);
 		close(pidfds[i]);
 	}

-- 
2.53.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/3] selftests/namespaces: Skip efault tests when listns() is not available
  2026-04-07 14:35 [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Ricardo B. Marlière
  2026-04-07 14:35 ` [PATCH 1/3] selftests/namespaces: Kill grandchild in nsid fixture teardown Ricardo B. Marlière
  2026-04-07 14:35 ` [PATCH 2/3] selftests/namespaces: Fix waitpid race in listns_efault_test cleanup Ricardo B. Marlière
@ 2026-04-07 14:35 ` Ricardo B. Marlière
  2026-04-09 13:06 ` [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Christian Brauner
  3 siblings, 0 replies; 5+ messages in thread
From: Ricardo B. Marlière @ 2026-04-07 14:35 UTC (permalink / raw)
  To: Shuah Khan, Christian Brauner
  Cc: linux-kselftest, linux-kernel, Ricardo B. Marliere

When listns() is not implemented the iterator child detects ENOSYS and
exits cleanly with status PIDFD_SKIP before the parent has a chance to
signal it.  The parent sends SIGKILL (which is a harmless no-op at that
point) and then calls waitpid(), obtaining a normal-exit status.  The
subsequent ASSERT_TRUE(WIFSIGNALED(status)) therefore fails, causing the
three EFAULT-focused tests to report FAIL rather than SKIP on kernels that
do not yet carry listns() support.

After collecting the iterator's exit status, check whether it exited with
PIDFD_SKIP and issue a SKIP verdict in that case, consistent with the
behaviour of every other listns test that already handles ENOSYS correctly.

Signed-off-by: Ricardo B. Marlière <rbm@suse.com>
---
 .../testing/selftests/namespaces/listns_efault_test.c  | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/tools/testing/selftests/namespaces/listns_efault_test.c b/tools/testing/selftests/namespaces/listns_efault_test.c
index ac3b208264f5..c20c6a812217 100644
--- a/tools/testing/selftests/namespaces/listns_efault_test.c
+++ b/tools/testing/selftests/namespaces/listns_efault_test.c
@@ -177,6 +177,12 @@ TEST(listns_partial_fault_with_ns_cleanup)
 	ASSERT_EQ(ret, iter_pid);
 	close(iter_pidfd);
 
+	/* If listns() is not supported the iterator exits cleanly via ENOSYS */
+	if (WIFEXITED(status) && WEXITSTATUS(status) == PIDFD_SKIP) {
+		munmap(map, page_size);
+		SKIP(return, "listns() not supported");
+	}
+
 	/* Should have been killed */
 	ASSERT_TRUE(WIFSIGNALED(status));
 	ASSERT_EQ(WTERMSIG(status), SIGKILL);
@@ -387,6 +393,12 @@ TEST(listns_late_fault_with_ns_cleanup)
 	ASSERT_EQ(ret, iter_pid);
 	close(iter_pidfd);
 
+	/* If listns() is not supported the iterator exits cleanly via ENOSYS */
+	if (WIFEXITED(status) && WEXITSTATUS(status) == PIDFD_SKIP) {
+		munmap(map, page_size);
+		SKIP(return, "listns() not supported");
+	}
+
 	/* Should have been killed */
 	ASSERT_TRUE(WIFSIGNALED(status));
 	ASSERT_EQ(WTERMSIG(status), SIGKILL);
@@ -523,6 +535,12 @@ TEST(listns_mnt_ns_cleanup_on_fault)
 	ASSERT_EQ(ret, iter_pid);
 	close(iter_pidfd);
 
+	/* If listns() is not supported the iterator exits cleanly via ENOSYS */
+	if (WIFEXITED(status) && WEXITSTATUS(status) == PIDFD_SKIP) {
+		munmap(map, page_size);
+		SKIP(return, "listns() not supported");
+	}
+
 	/* Should have been killed */
 	ASSERT_TRUE(WIFSIGNALED(status));
 	ASSERT_EQ(WTERMSIG(status), SIGKILL);

-- 
2.53.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures
  2026-04-07 14:35 [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Ricardo B. Marlière
                   ` (2 preceding siblings ...)
  2026-04-07 14:35 ` [PATCH 3/3] selftests/namespaces: Skip efault tests when listns() is not available Ricardo B. Marlière
@ 2026-04-09 13:06 ` Christian Brauner
  3 siblings, 0 replies; 5+ messages in thread
From: Christian Brauner @ 2026-04-09 13:06 UTC (permalink / raw)
  To: Shuah Khan, Ricardo B. Marlière
  Cc: Christian Brauner, linux-kselftest, linux-kernel

On Tue, 07 Apr 2026 11:35:44 -0300, Ricardo B. Marlière wrote:
> This series addresses three reliability problems in the namespaces selftest
> suite that cause tests to hang or report incorrect results.
> 
> The first patch fixes a hang in nsid_test where the grandchild process is
> not reaped during fixture teardown, leaving it alive and holding the TAP
> pipe write-end open so the test runner blocks indefinitely waiting for EOF.
> 
> [...]

Applied to the vfs-7.2.misc branch of the vfs/vfs.git tree.
Patches in the vfs-7.2.misc branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs-7.2.misc

[1/3] selftests/namespaces: Kill grandchild in nsid fixture teardown
      https://git.kernel.org/vfs/vfs/c/c87e78c29c78
[2/3] selftests/namespaces: Fix waitpid race in listns_efault_test cleanup
      https://git.kernel.org/vfs/vfs/c/f079c63caa7c
[3/3] selftests/namespaces: Skip efault tests when listns() is not available
      https://git.kernel.org/vfs/vfs/c/5bdb13872094

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-04-09 13:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-07 14:35 [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Ricardo B. Marlière
2026-04-07 14:35 ` [PATCH 1/3] selftests/namespaces: Kill grandchild in nsid fixture teardown Ricardo B. Marlière
2026-04-07 14:35 ` [PATCH 2/3] selftests/namespaces: Fix waitpid race in listns_efault_test cleanup Ricardo B. Marlière
2026-04-07 14:35 ` [PATCH 3/3] selftests/namespaces: Skip efault tests when listns() is not available Ricardo B. Marlière
2026-04-09 13:06 ` [PATCH 0/3] selftests/namespaces: Fix test hangs and false failures Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®