[LTP] [PATCH v2 5/5] syscalls: add listns02 functionality test

Andrea Cervesato
2026-03-13T11:50:21Z

From: Andrea Cervesato <andrea.cervesato@suse.com>

Add a simple test that create a namespace and verifies that listns02 is
listing it.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/listns/.gitignore | 1 +
testcases/kernel/syscalls/listns/listns02.c | 109 ++++++++++++++++++++++++++++
3 files changed, 111 insertions(+)

diff --git a/runtest/syscalls b/runtest/syscalls
index 769ce4a89a325ea09fdf2cfd42576697f23352c4..7d67f6ed2489e7281a07ae9f059b7485dd5f5f44 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -760,6 +760,7 @@ listmount03 listmount03
listmount04 listmount04

listns01 listns01
+listns02 listns02

listxattr01 listxattr01
listxattr02 listxattr02
diff --git a/testcases/kernel/syscalls/listns/.gitignore b/testcases/kernel/syscalls/listns/.gitignore
index 396d6b6fbfb3e34f17c79bfa3d5cc60f76477584..26d31ae372c54e0031a71b56f68cad44f32e5962 100644
--- a/testcases/kernel/syscalls/listns/.gitignore
+++ b/testcases/kernel/syscalls/listns/.gitignore
@@ -1 +1,2 @@
listns01
+listns02
diff --git a/testcases/kernel/syscalls/listns/listns02.c b/testcases/kernel/syscalls/listns/listns02.c
new file mode 100644
index 0000000000000000000000000000000000000000..8afe70ff952d0a49c9f32186485fc4ee7549c346
--- /dev/null
+++ b/testcases/kernel/syscalls/listns/listns02.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Basic listns() functionality test.
+ *
+ * [Algorithm]
+ *
+ * - Fork a child into a new namespace.
+ * - Read the child's namespace ID via NS_GET_ID ioctl on /proc/<pid>/ns/<type>.
+ * - Call listns() filtered by that namespace type.
+ * - Verify the child's namespace ID appears in the returned list.
+ */
+
+#define _GNU_SOURCE
+#include "tst_test.h"
+#include "lapi/syscalls.h"
+#include "lapi/ioctl_ns.h"
+#include "lapi/listns.h"
+
+#define NS_BUF_SIZE 256
+
+static pid_t child_pid = -1;
+static struct listns_req *req;
+
+static struct tcase {
+ const char *desc;
+ int clone_flag;
+ const char *ns_proc_name;
+} tcases[] = {
+ { "mount namespace", CLONE_NEWNS, "mnt" },
+ { "UTS namespace", CLONE_NEWUTS, "uts" },
+};
+
+static void verify_listns(unsigned int n)
+{
+ struct tcase *tc = &tcases[n];
+ char ns_path[64];
+ uint64_t ns_id;
+ uint64_t buf[NS_BUF_SIZE];
+ int fd, found;
+
+ req->size = NS_ID_REQ_SIZE_VER0;
+ req->ns_type = tc->clone_flag;
+
+ child_pid = SAFE_FORK();
+ if (!child_pid) {
+ TST_CHECKPOINT_WAIT(0);
+ SAFE_UNSHARE(tc->clone_flag);
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+ exit(0);
+ }
+
+ TST_CHECKPOINT_WAKE_AND_WAIT(0);
+
+ snprintf(ns_path, sizeof(ns_path), "/proc/%d/ns/%s",
+ child_pid, tc->ns_proc_name);
+
+ fd = SAFE_OPEN(ns_path, O_RDONLY);
+ SAFE_IOCTL(fd, NS_GET_ID, &ns_id);
+ SAFE_CLOSE(fd);
+
+ TEST(listns(req, buf, ARRAY_SIZE(buf), 0));
+
+ TST_CHECKPOINT_WAKE(0);
+
+ if (TST_RET < 0) {
+ tst_res(TFAIL | TTERRNO, "listns() failed for %s", tc->desc);
+ return;
+ }
+
+ found = 0;
+ for (int i = 0; i < TST_RET; i++) {
+ tst_res(TDEBUG, "buf[%d] = %lu", i, buf[i]);
+ if (buf[i] == ns_id) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ tst_res(TFAIL, "listns() did not return the created %s (ns_id=%lu)",
+ tc->desc, (unsigned long)ns_id);
+ else
+ tst_res(TPASS, "listns() correctly listed the created %s",
+ tc->desc);
+}
+
+static void setup(void)
+{
+ struct listns_req req = { .size = NS_ID_REQ_SIZE_VER0 };
+
+ tst_syscall(__NR_listns, &req, NULL, 0, 0);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcases),
+ .test = verify_listns,
+ .setup = setup,
+ .needs_root = 1,
+ .needs_checkpoints = 1,
+ .forks_child = 1,
+ .bufs = (struct tst_buffers []) {
+ {&req, .size = sizeof(*req)},
+ {},
+ },
+};

--
2.51.0