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