Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/filesystems/nsfs/iterate_mntns.c
26302 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
// Copyright (c) 2024 Christian Brauner <[email protected]>
3
4
#define _GNU_SOURCE
5
#include <fcntl.h>
6
#include <linux/auto_dev-ioctl.h>
7
#include <linux/errno.h>
8
#include <sched.h>
9
#include <stdio.h>
10
#include <string.h>
11
#include <sys/stat.h>
12
#include <sys/mount.h>
13
#include <unistd.h>
14
15
#include "../../kselftest_harness.h"
16
17
#define MNT_NS_COUNT 11
18
#define MNT_NS_LAST_INDEX 10
19
20
struct mnt_ns_info {
21
__u32 size;
22
__u32 nr_mounts;
23
__u64 mnt_ns_id;
24
};
25
26
#define MNT_NS_INFO_SIZE_VER0 16 /* size of first published struct */
27
28
/* Get information about namespace. */
29
#define NS_MNT_GET_INFO _IOR(0xb7, 10, struct mnt_ns_info)
30
/* Get next namespace. */
31
#define NS_MNT_GET_NEXT _IOR(0xb7, 11, struct mnt_ns_info)
32
/* Get previous namespace. */
33
#define NS_MNT_GET_PREV _IOR(0xb7, 12, struct mnt_ns_info)
34
35
FIXTURE(iterate_mount_namespaces) {
36
int fd_mnt_ns[MNT_NS_COUNT];
37
__u64 mnt_ns_id[MNT_NS_COUNT];
38
};
39
40
FIXTURE_SETUP(iterate_mount_namespaces)
41
{
42
for (int i = 0; i < MNT_NS_COUNT; i++)
43
self->fd_mnt_ns[i] = -EBADF;
44
45
/*
46
* Creating a new user namespace let's us guarantee that we only see
47
* mount namespaces that we did actually create.
48
*/
49
ASSERT_EQ(unshare(CLONE_NEWUSER), 0);
50
51
for (int i = 0; i < MNT_NS_COUNT; i++) {
52
struct mnt_ns_info info = {};
53
54
ASSERT_EQ(unshare(CLONE_NEWNS), 0);
55
self->fd_mnt_ns[i] = open("/proc/self/ns/mnt", O_RDONLY | O_CLOEXEC);
56
ASSERT_GE(self->fd_mnt_ns[i], 0);
57
ASSERT_EQ(ioctl(self->fd_mnt_ns[i], NS_MNT_GET_INFO, &info), 0);
58
self->mnt_ns_id[i] = info.mnt_ns_id;
59
}
60
}
61
62
FIXTURE_TEARDOWN(iterate_mount_namespaces)
63
{
64
for (int i = 0; i < MNT_NS_COUNT; i++) {
65
if (self->fd_mnt_ns[i] < 0)
66
continue;
67
ASSERT_EQ(close(self->fd_mnt_ns[i]), 0);
68
}
69
}
70
71
TEST_F(iterate_mount_namespaces, iterate_all_forward)
72
{
73
int fd_mnt_ns_cur, count = 0;
74
75
fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[0], F_DUPFD_CLOEXEC);
76
ASSERT_GE(fd_mnt_ns_cur, 0);
77
78
for (;; count++) {
79
struct mnt_ns_info info = {};
80
int fd_mnt_ns_next;
81
82
fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info);
83
if (fd_mnt_ns_next < 0 && errno == ENOENT)
84
break;
85
ASSERT_GE(fd_mnt_ns_next, 0);
86
ASSERT_EQ(close(fd_mnt_ns_cur), 0);
87
fd_mnt_ns_cur = fd_mnt_ns_next;
88
}
89
ASSERT_EQ(count, MNT_NS_LAST_INDEX);
90
}
91
92
TEST_F(iterate_mount_namespaces, iterate_all_backwards)
93
{
94
int fd_mnt_ns_cur, count = 0;
95
96
fd_mnt_ns_cur = fcntl(self->fd_mnt_ns[MNT_NS_LAST_INDEX], F_DUPFD_CLOEXEC);
97
ASSERT_GE(fd_mnt_ns_cur, 0);
98
99
for (;; count++) {
100
struct mnt_ns_info info = {};
101
int fd_mnt_ns_prev;
102
103
fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info);
104
if (fd_mnt_ns_prev < 0 && errno == ENOENT)
105
break;
106
ASSERT_GE(fd_mnt_ns_prev, 0);
107
ASSERT_EQ(close(fd_mnt_ns_cur), 0);
108
fd_mnt_ns_cur = fd_mnt_ns_prev;
109
}
110
ASSERT_EQ(count, MNT_NS_LAST_INDEX);
111
}
112
113
TEST_F(iterate_mount_namespaces, iterate_forward)
114
{
115
int fd_mnt_ns_cur;
116
117
ASSERT_EQ(setns(self->fd_mnt_ns[0], CLONE_NEWNS), 0);
118
119
fd_mnt_ns_cur = self->fd_mnt_ns[0];
120
for (int i = 1; i < MNT_NS_COUNT; i++) {
121
struct mnt_ns_info info = {};
122
int fd_mnt_ns_next;
123
124
fd_mnt_ns_next = ioctl(fd_mnt_ns_cur, NS_MNT_GET_NEXT, &info);
125
ASSERT_GE(fd_mnt_ns_next, 0);
126
ASSERT_EQ(close(fd_mnt_ns_cur), 0);
127
fd_mnt_ns_cur = fd_mnt_ns_next;
128
ASSERT_EQ(info.mnt_ns_id, self->mnt_ns_id[i]);
129
}
130
}
131
132
TEST_F(iterate_mount_namespaces, iterate_backward)
133
{
134
int fd_mnt_ns_cur;
135
136
ASSERT_EQ(setns(self->fd_mnt_ns[MNT_NS_LAST_INDEX], CLONE_NEWNS), 0);
137
138
fd_mnt_ns_cur = self->fd_mnt_ns[MNT_NS_LAST_INDEX];
139
for (int i = MNT_NS_LAST_INDEX - 1; i >= 0; i--) {
140
struct mnt_ns_info info = {};
141
int fd_mnt_ns_prev;
142
143
fd_mnt_ns_prev = ioctl(fd_mnt_ns_cur, NS_MNT_GET_PREV, &info);
144
ASSERT_GE(fd_mnt_ns_prev, 0);
145
ASSERT_EQ(close(fd_mnt_ns_cur), 0);
146
fd_mnt_ns_cur = fd_mnt_ns_prev;
147
ASSERT_EQ(info.mnt_ns_id, self->mnt_ns_id[i]);
148
}
149
}
150
151
TEST_F(iterate_mount_namespaces, nfs_valid_ioctl)
152
{
153
ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_OPENMOUNT, NULL), 0);
154
ASSERT_EQ(errno, ENOTTY);
155
156
ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_CLOSEMOUNT, NULL), 0);
157
ASSERT_EQ(errno, ENOTTY);
158
159
ASSERT_NE(ioctl(self->fd_mnt_ns[0], AUTOFS_DEV_IOCTL_READY, NULL), 0);
160
ASSERT_EQ(errno, ENOTTY);
161
}
162
163
TEST_HARNESS_MAIN
164
165