xref: /linux/tools/testing/selftests/filesystems/empty_mntns/root_readdir_test.c (revision 8ac49fbf00e580e8ee1a66b120f8b33d9ab81901)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Reading the root of an empty mount namespace holds nothing that anybody
4  * else waits for: the directory never has an entry, so a readdir stuck in
5  * the page fault of its buffer stalls neither a create nor a lookup in it.
6  */
7 #define _GNU_SOURCE
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <sched.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 
15 #include "../../kselftest_harness.h"
16 #include "../readdir_hold.h"
17 #include "empty_mntns.h"
18 
19 TEST(readdir_blocks_nobody)
20 {
21 	struct readdir_hold hold;
22 	bool stalled;
23 	int dfd;
24 
25 	if (geteuid())
26 		SKIP(return, "test requires root");
27 	if (readdir_hold_init(&hold))
28 		SKIP(return, "test requires userfaultfd");
29 	if (unshare(UNSHARE_EMPTY_MNTNS)) {
30 		readdir_hold_destroy(&hold);
31 		if (errno == EINVAL)
32 			SKIP(return, "UNSHARE_EMPTY_MNTNS not supported");
33 		ASSERT_TRUE(false)
34 			TH_LOG("unshare(UNSHARE_EMPTY_MNTNS): %m");
35 	}
36 	dfd = open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
37 	ASSERT_GE(dfd, 0);
38 	ASSERT_EQ(readdir_hold_check(&hold, dfd, &stalled), 0);
39 	/* the lookup came back while the readdir was stuck in its fault */
40 	EXPECT_FALSE(stalled);
41 	close(dfd);
42 	readdir_hold_destroy(&hold);
43 }
44 
45 TEST_HARNESS_MAIN
46