aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/filesystems/empty_mntns/root_readdir_test.c
blob: 0ff54424702701f906c527b7d85bfb4fd408d3ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// SPDX-License-Identifier: GPL-2.0
/*
 * Reading the root of an empty mount namespace holds nothing that anybody
 * else waits for: the directory never has an entry, so a readdir stuck in
 * the page fault of its buffer stalls neither a create nor a lookup in it.
 */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "../../kselftest_harness.h"
#include "../readdir_hold.h"
#include "empty_mntns.h"

TEST(readdir_blocks_nobody)
{
	struct readdir_hold hold;
	bool stalled;
	int dfd;

	if (geteuid())
		SKIP(return, "test requires root");
	if (readdir_hold_init(&hold))
		SKIP(return, "test requires userfaultfd");
	if (unshare(UNSHARE_EMPTY_MNTNS)) {
		readdir_hold_destroy(&hold);
		if (errno == EINVAL)
			SKIP(return, "UNSHARE_EMPTY_MNTNS not supported");
		ASSERT_TRUE(false)
			TH_LOG("unshare(UNSHARE_EMPTY_MNTNS): %m");
	}
	dfd = open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
	ASSERT_GE(dfd, 0);
	ASSERT_EQ(readdir_hold_check(&hold, dfd, &stalled), 0);
	/* the lookup came back while the readdir was stuck in its fault */
	EXPECT_FALSE(stalled);
	close(dfd);
	readdir_hold_destroy(&hold);
}

TEST_HARNESS_MAIN