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