Skip to content

Commit d896f71

Browse files
josefbacikbrauner
authored andcommitted
selftests: add a test for the foreign mnt ns extensions
This tests both statmount and listmount to make sure they work with the extensions that allow us to specify a mount ns to enter in order to find the mount entries. Signed-off-by: Josef Bacik <[email protected]> Link: https://lore.kernel.org/r/2d1a35bc9ab94b4656c056c420f25e429e7eb0b1.1719243756.git.josef@toxicpanda.com Signed-off-by: Christian Brauner <[email protected]>
1 parent e8e43a1 commit d896f71

File tree

4 files changed

+424
-41
lines changed

4 files changed

+424
-41
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0-or-later
22

33
CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES)
4-
TEST_GEN_PROGS := statmount_test
4+
TEST_GEN_PROGS := statmount_test statmount_test_ns
55

66
include ../../lib.mk
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#ifndef __STATMOUNT_H
4+
#define __STATMOUNT_H
5+
6+
#include <stdint.h>
7+
#include <linux/mount.h>
8+
#include <asm/unistd.h>
9+
10+
static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint64_t mask,
11+
struct statmount *buf, size_t bufsize,
12+
unsigned int flags)
13+
{
14+
struct mnt_id_req req = {
15+
.size = MNT_ID_REQ_SIZE_VER0,
16+
.mnt_id = mnt_id,
17+
.param = mask,
18+
};
19+
20+
if (mnt_ns_id) {
21+
req.size = MNT_ID_REQ_SIZE_VER1;
22+
req.mnt_ns_id = mnt_ns_id;
23+
}
24+
25+
return syscall(__NR_statmount, &req, buf, bufsize, flags);
26+
}
27+
28+
static ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id,
29+
uint64_t last_mnt_id, uint64_t list[], size_t num,
30+
unsigned int flags)
31+
{
32+
struct mnt_id_req req = {
33+
.size = MNT_ID_REQ_SIZE_VER0,
34+
.mnt_id = mnt_id,
35+
.param = last_mnt_id,
36+
};
37+
38+
if (mnt_ns_id) {
39+
req.size = MNT_ID_REQ_SIZE_VER1;
40+
req.mnt_ns_id = mnt_ns_id;
41+
}
42+
43+
return syscall(__NR_listmount, &req, list, num, flags);
44+
}
45+
46+
#endif /* __STATMOUNT_H */

tools/testing/selftests/filesystems/statmount/statmount_test.c

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,15 @@
44

55
#include <assert.h>
66
#include <stddef.h>
7-
#include <stdint.h>
87
#include <sched.h>
98
#include <fcntl.h>
109
#include <sys/param.h>
1110
#include <sys/mount.h>
1211
#include <sys/stat.h>
1312
#include <sys/statfs.h>
14-
#include <linux/mount.h>
1513
#include <linux/stat.h>
16-
#include <asm/unistd.h>
1714

15+
#include "statmount.h"
1816
#include "../../kselftest.h"
1917

2018
static const char *const known_fs[] = {
@@ -36,18 +34,6 @@ static const char *const known_fs[] = {
3634
"ufs", "v7", "vboxsf", "vfat", "virtiofs", "vxfs", "xenfs", "xfs",
3735
"zonefs", NULL };
3836

39-
static int statmount(uint64_t mnt_id, uint64_t mask, struct statmount *buf,
40-
size_t bufsize, unsigned int flags)
41-
{
42-
struct mnt_id_req req = {
43-
.size = MNT_ID_REQ_SIZE_VER0,
44-
.mnt_id = mnt_id,
45-
.param = mask,
46-
};
47-
48-
return syscall(__NR_statmount, &req, buf, bufsize, flags);
49-
}
50-
5137
static struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mask, unsigned int flags)
5238
{
5339
size_t bufsize = 1 << 15;
@@ -56,7 +42,7 @@ static struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mask, unsigne
5642
int ret;
5743

5844
for (;;) {
59-
ret = statmount(mnt_id, mask, tmp, bufsize, flags);
45+
ret = statmount(mnt_id, 0, mask, tmp, bufsize, flags);
6046
if (ret != -1)
6147
break;
6248
if (tofree)
@@ -122,7 +108,6 @@ static int orig_root;
122108
static uint64_t root_id, parent_id;
123109
static uint32_t old_root_id, old_parent_id;
124110

125-
126111
static void cleanup_namespace(void)
127112
{
128113
fchdir(orig_root);
@@ -138,7 +123,7 @@ static void setup_namespace(void)
138123
uid_t uid = getuid();
139124
gid_t gid = getgid();
140125

141-
ret = unshare(CLONE_NEWNS|CLONE_NEWUSER);
126+
ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID);
142127
if (ret == -1)
143128
ksft_exit_fail_msg("unsharing mountns and userns: %s\n",
144129
strerror(errno));
@@ -208,25 +193,13 @@ static int setup_mount_tree(int log2_num)
208193
return 0;
209194
}
210195

211-
static ssize_t listmount(uint64_t mnt_id, uint64_t last_mnt_id,
212-
uint64_t list[], size_t num, unsigned int flags)
213-
{
214-
struct mnt_id_req req = {
215-
.size = MNT_ID_REQ_SIZE_VER0,
216-
.mnt_id = mnt_id,
217-
.param = last_mnt_id,
218-
};
219-
220-
return syscall(__NR_listmount, &req, list, num, flags);
221-
}
222-
223196
static void test_listmount_empty_root(void)
224197
{
225198
ssize_t res;
226199
const unsigned int size = 32;
227200
uint64_t list[size];
228201

229-
res = listmount(LSMT_ROOT, 0, list, size, 0);
202+
res = listmount(LSMT_ROOT, 0, 0, list, size, 0);
230203
if (res == -1) {
231204
ksft_test_result_fail("listmount: %s\n", strerror(errno));
232205
return;
@@ -251,7 +224,7 @@ static void test_statmount_zero_mask(void)
251224
struct statmount sm;
252225
int ret;
253226

254-
ret = statmount(root_id, 0, &sm, sizeof(sm), 0);
227+
ret = statmount(root_id, 0, 0, &sm, sizeof(sm), 0);
255228
if (ret == -1) {
256229
ksft_test_result_fail("statmount zero mask: %s\n",
257230
strerror(errno));
@@ -277,7 +250,7 @@ static void test_statmount_mnt_basic(void)
277250
int ret;
278251
uint64_t mask = STATMOUNT_MNT_BASIC;
279252

280-
ret = statmount(root_id, mask, &sm, sizeof(sm), 0);
253+
ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0);
281254
if (ret == -1) {
282255
ksft_test_result_fail("statmount mnt basic: %s\n",
283256
strerror(errno));
@@ -337,7 +310,7 @@ static void test_statmount_sb_basic(void)
337310
struct statx sx;
338311
struct statfs sf;
339312

340-
ret = statmount(root_id, mask, &sm, sizeof(sm), 0);
313+
ret = statmount(root_id, 0, mask, &sm, sizeof(sm), 0);
341314
if (ret == -1) {
342315
ksft_test_result_fail("statmount sb basic: %s\n",
343316
strerror(errno));
@@ -498,14 +471,14 @@ static void test_statmount_string(uint64_t mask, size_t off, const char *name)
498471
exactsize = sm->size;
499472
shortsize = sizeof(*sm) + i;
500473

501-
ret = statmount(root_id, mask, sm, exactsize, 0);
474+
ret = statmount(root_id, 0, mask, sm, exactsize, 0);
502475
if (ret == -1) {
503476
ksft_test_result_fail("statmount exact size: %s\n",
504477
strerror(errno));
505478
goto out;
506479
}
507480
errno = 0;
508-
ret = statmount(root_id, mask, sm, shortsize, 0);
481+
ret = statmount(root_id, 0, mask, sm, shortsize, 0);
509482
if (ret != -1 || errno != EOVERFLOW) {
510483
ksft_test_result_fail("should have failed with EOVERFLOW: %s\n",
511484
strerror(errno));
@@ -533,7 +506,7 @@ static void test_listmount_tree(void)
533506
if (res == -1)
534507
return;
535508

536-
num = res = listmount(LSMT_ROOT, 0, list, size, 0);
509+
num = res = listmount(LSMT_ROOT, 0, 0, list, size, 0);
537510
if (res == -1) {
538511
ksft_test_result_fail("listmount: %s\n", strerror(errno));
539512
return;
@@ -545,7 +518,7 @@ static void test_listmount_tree(void)
545518
}
546519

547520
for (i = 0; i < size - step;) {
548-
res = listmount(LSMT_ROOT, i ? list2[i - 1] : 0, list2 + i, step, 0);
521+
res = listmount(LSMT_ROOT, 0, i ? list2[i - 1] : 0, list2 + i, step, 0);
549522
if (res == -1)
550523
ksft_test_result_fail("short listmount: %s\n",
551524
strerror(errno));
@@ -577,11 +550,11 @@ int main(void)
577550
int ret;
578551
uint64_t all_mask = STATMOUNT_SB_BASIC | STATMOUNT_MNT_BASIC |
579552
STATMOUNT_PROPAGATE_FROM | STATMOUNT_MNT_ROOT |
580-
STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE;
553+
STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE | STATMOUNT_MNT_NS_ID;
581554

582555
ksft_print_header();
583556

584-
ret = statmount(0, 0, NULL, 0, 0);
557+
ret = statmount(0, 0, 0, NULL, 0, 0);
585558
assert(ret == -1);
586559
if (errno == ENOSYS)
587560
ksft_exit_skip("statmount() syscall not supported\n");

0 commit comments

Comments
 (0)