1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
4f08c3bdfSopenharmony_ci * Author: Dai Shili <daisl.fnst@fujitsu.com>
5f08c3bdfSopenharmony_ci * Author: Chen Hanxiao <chenhx.fnst@fujitsu.com>
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * Basic mount_setattr() test.
12f08c3bdfSopenharmony_ci * Test whether the basic mount attributes are set correctly.
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * Verify some MOUNT_SETATTR(2) attributes:
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci * - MOUNT_ATTR_RDONLY - makes the mount read-only
17f08c3bdfSopenharmony_ci * - MOUNT_ATTR_NOSUID - causes the mount not to honor the
18f08c3bdfSopenharmony_ci *   set-user-ID and set-group-ID mode bits and file capabilities
19f08c3bdfSopenharmony_ci *   when executing programs.
20f08c3bdfSopenharmony_ci * - MOUNT_ATTR_NODEV - prevents access to devices on this mount
21f08c3bdfSopenharmony_ci * - MOUNT_ATTR_NOEXEC - prevents executing programs on this mount
22f08c3bdfSopenharmony_ci * - MOUNT_ATTR_NOSYMFOLLOW - prevents following symbolic links
23f08c3bdfSopenharmony_ci *   on this mount
24f08c3bdfSopenharmony_ci * - MOUNT_ATTR_NODIRATIME - prevents updating access time for
25f08c3bdfSopenharmony_ci *   directories on this mount
26f08c3bdfSopenharmony_ci *
27f08c3bdfSopenharmony_ci * The functionality was added in v5.12.
28f08c3bdfSopenharmony_ci */
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_ci#define _GNU_SOURCE
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_ci#include <sys/statvfs.h>
33f08c3bdfSopenharmony_ci#include "tst_test.h"
34f08c3bdfSopenharmony_ci#include "lapi/fsmount.h"
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci#define MNTPOINT        "mntpoint"
37f08c3bdfSopenharmony_ci#define OT_MNTPOINT     "ot_mntpoint"
38f08c3bdfSopenharmony_ci#define TCASE_ENTRY(attrs, exp_attrs)   \
39f08c3bdfSopenharmony_ci	{                                \
40f08c3bdfSopenharmony_ci		.name = #attrs,                 \
41f08c3bdfSopenharmony_ci		.mount_attrs = attrs,           \
42f08c3bdfSopenharmony_ci		.expect_attrs = exp_attrs       \
43f08c3bdfSopenharmony_ci	}
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_cistatic int mount_flag, otfd = -1;
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_cistatic struct tcase {
48f08c3bdfSopenharmony_ci	char *name;
49f08c3bdfSopenharmony_ci	unsigned int mount_attrs;
50f08c3bdfSopenharmony_ci	unsigned int expect_attrs;
51f08c3bdfSopenharmony_ci} tcases[] = {
52f08c3bdfSopenharmony_ci	TCASE_ENTRY(MOUNT_ATTR_RDONLY, ST_RDONLY),
53f08c3bdfSopenharmony_ci	TCASE_ENTRY(MOUNT_ATTR_NOSUID, ST_NOSUID),
54f08c3bdfSopenharmony_ci	TCASE_ENTRY(MOUNT_ATTR_NODEV, ST_NODEV),
55f08c3bdfSopenharmony_ci	TCASE_ENTRY(MOUNT_ATTR_NOEXEC, ST_NOEXEC),
56f08c3bdfSopenharmony_ci	TCASE_ENTRY(MOUNT_ATTR_NOSYMFOLLOW, ST_NOSYMFOLLOW),
57f08c3bdfSopenharmony_ci	TCASE_ENTRY(MOUNT_ATTR_NODIRATIME, ST_NODIRATIME),
58f08c3bdfSopenharmony_ci};
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_cistatic void cleanup(void)
61f08c3bdfSopenharmony_ci{
62f08c3bdfSopenharmony_ci	if (otfd > -1)
63f08c3bdfSopenharmony_ci		SAFE_CLOSE(otfd);
64f08c3bdfSopenharmony_ci	if (mount_flag)
65f08c3bdfSopenharmony_ci		SAFE_UMOUNT(OT_MNTPOINT);
66f08c3bdfSopenharmony_ci}
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_cistatic void setup(void)
69f08c3bdfSopenharmony_ci{
70f08c3bdfSopenharmony_ci	fsopen_supported_by_kernel();
71f08c3bdfSopenharmony_ci	struct stat st = {0};
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	if (stat(OT_MNTPOINT, &st) == -1)
74f08c3bdfSopenharmony_ci		SAFE_MKDIR(OT_MNTPOINT, 0777);
75f08c3bdfSopenharmony_ci}
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_cistatic void run(unsigned int n)
78f08c3bdfSopenharmony_ci{
79f08c3bdfSopenharmony_ci	struct tcase *tc = &tcases[n];
80f08c3bdfSopenharmony_ci	struct mount_attr attr = {
81f08c3bdfSopenharmony_ci		.attr_set = tc->mount_attrs,
82f08c3bdfSopenharmony_ci	};
83f08c3bdfSopenharmony_ci	struct statvfs buf;
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_ci	TST_EXP_FD_SILENT(open_tree(AT_FDCWD, MNTPOINT, AT_EMPTY_PATH |
86f08c3bdfSopenharmony_ci		AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE));
87f08c3bdfSopenharmony_ci	if (!TST_PASS)
88f08c3bdfSopenharmony_ci		return;
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ci	otfd = (int)TST_RET;
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_ci	TST_EXP_PASS_SILENT(mount_setattr(otfd, "", AT_EMPTY_PATH, &attr, sizeof(attr)),
93f08c3bdfSopenharmony_ci		"%s set", tc->name);
94f08c3bdfSopenharmony_ci	if (!TST_PASS)
95f08c3bdfSopenharmony_ci		goto out1;
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	TST_EXP_PASS_SILENT(move_mount(otfd, "", AT_FDCWD, OT_MNTPOINT, MOVE_MOUNT_F_EMPTY_PATH));
98f08c3bdfSopenharmony_ci	if (!TST_PASS)
99f08c3bdfSopenharmony_ci		goto out1;
100f08c3bdfSopenharmony_ci	mount_flag = 1;
101f08c3bdfSopenharmony_ci	SAFE_CLOSE(otfd);
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_ci	TST_EXP_PASS_SILENT(statvfs(OT_MNTPOINT, &buf), "statvfs sucess");
104f08c3bdfSopenharmony_ci	if (!TST_PASS)
105f08c3bdfSopenharmony_ci		goto out2;
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	if (buf.f_flag & tc->expect_attrs)
108f08c3bdfSopenharmony_ci		tst_res(TPASS, "%s is actually set as expected", tc->name);
109f08c3bdfSopenharmony_ci	else
110f08c3bdfSopenharmony_ci		tst_res(TFAIL, "%s is not actually set as expected", tc->name);
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ci	goto out2;
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ciout1:
115f08c3bdfSopenharmony_ci	SAFE_CLOSE(otfd);
116f08c3bdfSopenharmony_ciout2:
117f08c3bdfSopenharmony_ci	if (mount_flag)
118f08c3bdfSopenharmony_ci		SAFE_UMOUNT(OT_MNTPOINT);
119f08c3bdfSopenharmony_ci
120f08c3bdfSopenharmony_ci	mount_flag = 0;
121f08c3bdfSopenharmony_ci}
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_cistatic struct tst_test test = {
124f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
125f08c3bdfSopenharmony_ci	.test = run,
126f08c3bdfSopenharmony_ci	.setup = setup,
127f08c3bdfSopenharmony_ci	.cleanup = cleanup,
128f08c3bdfSopenharmony_ci	.needs_root = 1,
129f08c3bdfSopenharmony_ci	.mount_device = 1,
130f08c3bdfSopenharmony_ci	.mntpoint = MNTPOINT,
131f08c3bdfSopenharmony_ci	.all_filesystems = 1,
132f08c3bdfSopenharmony_ci	.skip_filesystems = (const char *const []){"fuse", NULL},
133f08c3bdfSopenharmony_ci};
134