1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2020 Red Hat, Inc. All rights reserved.
4 * Author: Zorro Lang <zlang@redhat.com>
5 *
6 * Basic fsmount() test.
7 */
8
9 #include "tst_test.h"
10 #include "lapi/fsmount.h"
11
12 #define MNTPOINT "mntpoint"
13
14 #define TCASE_ENTRY(_flags, _attrs) {.name = "Flag " #_flags ", Attr " #_attrs, .flags = _flags, .attrs = _attrs}
15
16 static struct tcase {
17 char *name;
18 unsigned int flags;
19 unsigned int attrs;
20 } tcases[] = {
21 TCASE_ENTRY(0, MOUNT_ATTR_RDONLY),
22 TCASE_ENTRY(0, MOUNT_ATTR_NOSUID),
23 TCASE_ENTRY(0, MOUNT_ATTR_NODEV),
24 TCASE_ENTRY(0, MOUNT_ATTR_NOEXEC),
25 TCASE_ENTRY(0, MOUNT_ATTR_RELATIME),
26 TCASE_ENTRY(0, MOUNT_ATTR_NOATIME),
27 TCASE_ENTRY(0, MOUNT_ATTR_STRICTATIME),
28 TCASE_ENTRY(0, MOUNT_ATTR_NODIRATIME),
29 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_RDONLY),
30 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_NOSUID),
31 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_NODEV),
32 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_NOEXEC),
33 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_RELATIME),
34 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_NOATIME),
35 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_STRICTATIME),
36 TCASE_ENTRY(FSMOUNT_CLOEXEC, MOUNT_ATTR_NODIRATIME),
37 };
38
run(unsigned int n)39 static void run(unsigned int n)
40 {
41 struct tcase *tc = &tcases[n];
42 int sfd, mfd;
43
44 TEST(sfd = fsopen(tst_device->fs_type, FSOPEN_CLOEXEC));
45 if (sfd == -1) {
46 tst_res(TFAIL | TTERRNO, "fsopen() on %s failed",
47 tst_device->fs_type);
48 return;
49 }
50
51 TEST(fsconfig(sfd, FSCONFIG_SET_STRING, "source", tst_device->dev, 0));
52 if (TST_RET == -1) {
53 SAFE_CLOSE(sfd);
54 tst_res(TFAIL | TTERRNO,
55 "fsconfig(FSCONFIG_SET_STRING) failed to set source to %s", tst_device->dev);
56 return;
57 }
58
59 TEST(fsconfig(sfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
60 if (TST_RET == -1) {
61 SAFE_CLOSE(sfd);
62 tst_res(TFAIL | TTERRNO, "fsconfig(FSCONFIG_CMD_CREATE) failed");
63 return;
64 }
65
66 TEST(mfd = fsmount(sfd, tc->flags, tc->attrs));
67 SAFE_CLOSE(sfd);
68
69 if (mfd == -1) {
70 tst_res(TFAIL | TTERRNO,
71 "fsmount() failed to create a mount object");
72 return;
73 }
74
75 TEST(move_mount(mfd, "", AT_FDCWD, MNTPOINT, MOVE_MOUNT_F_EMPTY_PATH));
76 SAFE_CLOSE(mfd);
77
78 if (TST_RET == -1) {
79 tst_res(TFAIL | TTERRNO,
80 "move_mount() failed to attach to the mount point");
81 return;
82 }
83
84 if (tst_is_mounted_at_tmpdir(MNTPOINT)) {
85 SAFE_UMOUNT(MNTPOINT);
86 tst_res(TPASS, "%s: fsmount() passed", tc->name);
87 }
88 }
89
90 static struct tst_test test = {
91 .tcnt = ARRAY_SIZE(tcases),
92 .test = run,
93 .setup = fsopen_supported_by_kernel,
94 .needs_root = 1,
95 .mntpoint = MNTPOINT,
96 .format_device = 1,
97 .all_filesystems = 1,
98 .skip_filesystems = (const char *const []){"fuse", NULL},
99 };
100