[PATCH 3/3] selftests/landlock: Clean up TMP_DIR and retry if dir already exists

Tingmao Wang m at maowtm.org
Sat May 24 17:56:34 UTC 2025


This ensures that if for whatever reason FIXTURE_SETUP fails, the next
test run will handle this gracefully.

I don't actually 100% like this approach - maybe we should consider
enhancing the test framework to add a FIXTURE_TEARDOWN_ALWAYS, that will
run even if FIXTURE_SETUP fails?

Signed-off-by: Tingmao Wang <m at maowtm.org>
---
 tools/testing/selftests/landlock/fs_test.c | 44 ++++++++++++++++++++--
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
index 21ed8afcc060..e6891f59803a 100644
--- a/tools/testing/selftests/landlock/fs_test.c
+++ b/tools/testing/selftests/landlock/fs_test.c
@@ -233,12 +233,41 @@ maybe_warn_about_permission_on_cwd(struct __test_metadata *const _metadata,
 	}
 }
 
+static int try_teardown_layout(struct __test_metadata *const _metadata)
+{
+	struct stat stat_buf;
+
+	if (stat(TMP_DIR, &stat_buf) < 0) {
+		return -1;
+	}
+
+	TH_LOG("Attempting to cleanup layout and retry...");
+
+	if (umount(TMP_DIR)) {
+		if (errno != EINVAL && errno != ENOENT) {
+			TH_LOG("Failed to unmount directory \"%s\": %s",
+			       TMP_DIR, strerror(errno));
+			return -1;
+		}
+	}
+	if (rmdir(TMP_DIR)) {
+		if (errno != ENOENT) {
+			TH_LOG("Failed to remove directory \"%s\": %s", TMP_DIR,
+			       strerror(errno));
+			return -1;
+		}
+	}
+	return 0;
+}
+
 static void create_directory(struct __test_metadata *const _metadata,
 			     const char *const path)
 {
+	bool retried = false;
+
+retry:
 	mkdir_parents(_metadata, path);
-	ASSERT_EQ(0, mkdir(path, 0700))
-	{
+	if (mkdir(path, 0700)) {
 		int err = errno;
 
 		TH_LOG("Failed to create directory \"%s\": %s", path,
@@ -246,7 +275,14 @@ static void create_directory(struct __test_metadata *const _metadata,
 
 		if (strcmp(path, TMP_DIR) == 0) {
 			maybe_warn_about_permission_on_cwd(_metadata, err);
+			if (!retried && errno == EEXIST &&
+			    !try_teardown_layout(_metadata)) {
+				retried = true;
+				goto retry;
+			}
 		}
+
+		ASSERT_TRUE(false);
 	}
 }
 
@@ -320,13 +356,15 @@ static void prepare_layout_opt(struct __test_metadata *const _metadata,
 {
 	disable_caps(_metadata);
 	umask(0077);
+
+	/* create_directory may try umounting then rmdir if tmp already mounted */
+	set_cap(_metadata, CAP_SYS_ADMIN);
 	create_directory(_metadata, TMP_DIR);
 
 	/*
 	 * Do not pollute the rest of the system: creates a private mount point
 	 * for tests relying on pivot_root(2) and move_mount(2).
 	 */
-	set_cap(_metadata, CAP_SYS_ADMIN);
 	ASSERT_EQ(0, unshare(CLONE_NEWNS | CLONE_NEWCGROUP))
 	{
 		TH_LOG("Failed to create new mount namespace: %s",
-- 
2.49.0




More information about the Linux-security-module-archive mailing list