xref: /openbmc/linux/tools/testing/selftests/mount/unprivileged-remount-test.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2db181ce0SEric W. Biederman #define _GNU_SOURCE
3db181ce0SEric W. Biederman #include <sched.h>
4db181ce0SEric W. Biederman #include <stdio.h>
5db181ce0SEric W. Biederman #include <errno.h>
6db181ce0SEric W. Biederman #include <string.h>
7db181ce0SEric W. Biederman #include <sys/types.h>
8db181ce0SEric W. Biederman #include <sys/mount.h>
9db181ce0SEric W. Biederman #include <sys/wait.h>
104a44a19bSEric W. Biederman #include <sys/vfs.h>
114a44a19bSEric W. Biederman #include <sys/statvfs.h>
12db181ce0SEric W. Biederman #include <stdlib.h>
13db181ce0SEric W. Biederman #include <unistd.h>
14db181ce0SEric W. Biederman #include <fcntl.h>
15db181ce0SEric W. Biederman #include <grp.h>
16db181ce0SEric W. Biederman #include <stdbool.h>
17db181ce0SEric W. Biederman #include <stdarg.h>
18db181ce0SEric W. Biederman 
19db181ce0SEric W. Biederman #ifndef CLONE_NEWNS
20db181ce0SEric W. Biederman # define CLONE_NEWNS 0x00020000
21db181ce0SEric W. Biederman #endif
22db181ce0SEric W. Biederman #ifndef CLONE_NEWUTS
23db181ce0SEric W. Biederman # define CLONE_NEWUTS 0x04000000
24db181ce0SEric W. Biederman #endif
25db181ce0SEric W. Biederman #ifndef CLONE_NEWIPC
26db181ce0SEric W. Biederman # define CLONE_NEWIPC 0x08000000
27db181ce0SEric W. Biederman #endif
28db181ce0SEric W. Biederman #ifndef CLONE_NEWNET
29db181ce0SEric W. Biederman # define CLONE_NEWNET 0x40000000
30db181ce0SEric W. Biederman #endif
31db181ce0SEric W. Biederman #ifndef CLONE_NEWUSER
32db181ce0SEric W. Biederman # define CLONE_NEWUSER 0x10000000
33db181ce0SEric W. Biederman #endif
34db181ce0SEric W. Biederman #ifndef CLONE_NEWPID
35db181ce0SEric W. Biederman # define CLONE_NEWPID 0x20000000
36db181ce0SEric W. Biederman #endif
37db181ce0SEric W. Biederman 
384a44a19bSEric W. Biederman #ifndef MS_REC
394a44a19bSEric W. Biederman # define MS_REC 16384
404a44a19bSEric W. Biederman #endif
41db181ce0SEric W. Biederman #ifndef MS_RELATIME
42db181ce0SEric W. Biederman # define MS_RELATIME (1 << 21)
43db181ce0SEric W. Biederman #endif
44db181ce0SEric W. Biederman #ifndef MS_STRICTATIME
45db181ce0SEric W. Biederman # define MS_STRICTATIME (1 << 24)
46db181ce0SEric W. Biederman #endif
47db181ce0SEric W. Biederman 
die(char * fmt,...)48db181ce0SEric W. Biederman static void die(char *fmt, ...)
49db181ce0SEric W. Biederman {
50db181ce0SEric W. Biederman 	va_list ap;
51db181ce0SEric W. Biederman 	va_start(ap, fmt);
52db181ce0SEric W. Biederman 	vfprintf(stderr, fmt, ap);
53db181ce0SEric W. Biederman 	va_end(ap);
54db181ce0SEric W. Biederman 	exit(EXIT_FAILURE);
55db181ce0SEric W. Biederman }
56db181ce0SEric W. Biederman 
vmaybe_write_file(bool enoent_ok,char * filename,char * fmt,va_list ap)57db86da7cSEric W. Biederman static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
58db181ce0SEric W. Biederman {
59db181ce0SEric W. Biederman 	char buf[4096];
60db181ce0SEric W. Biederman 	int fd;
61db181ce0SEric W. Biederman 	ssize_t written;
62db181ce0SEric W. Biederman 	int buf_len;
63db181ce0SEric W. Biederman 
64db181ce0SEric W. Biederman 	buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
65db181ce0SEric W. Biederman 	if (buf_len < 0) {
66db181ce0SEric W. Biederman 		die("vsnprintf failed: %s\n",
67db181ce0SEric W. Biederman 		    strerror(errno));
68db181ce0SEric W. Biederman 	}
69db181ce0SEric W. Biederman 	if (buf_len >= sizeof(buf)) {
70db181ce0SEric W. Biederman 		die("vsnprintf output truncated\n");
71db181ce0SEric W. Biederman 	}
72db181ce0SEric W. Biederman 
73db181ce0SEric W. Biederman 	fd = open(filename, O_WRONLY);
74db181ce0SEric W. Biederman 	if (fd < 0) {
75db86da7cSEric W. Biederman 		if ((errno == ENOENT) && enoent_ok)
76db86da7cSEric W. Biederman 			return;
77db181ce0SEric W. Biederman 		die("open of %s failed: %s\n",
78db181ce0SEric W. Biederman 		    filename, strerror(errno));
79db181ce0SEric W. Biederman 	}
80db181ce0SEric W. Biederman 	written = write(fd, buf, buf_len);
81db181ce0SEric W. Biederman 	if (written != buf_len) {
82db181ce0SEric W. Biederman 		if (written >= 0) {
83db181ce0SEric W. Biederman 			die("short write to %s\n", filename);
84db181ce0SEric W. Biederman 		} else {
85db181ce0SEric W. Biederman 			die("write to %s failed: %s\n",
86db181ce0SEric W. Biederman 				filename, strerror(errno));
87db181ce0SEric W. Biederman 		}
88db181ce0SEric W. Biederman 	}
89db181ce0SEric W. Biederman 	if (close(fd) != 0) {
90db181ce0SEric W. Biederman 		die("close of %s failed: %s\n",
91db181ce0SEric W. Biederman 			filename, strerror(errno));
92db181ce0SEric W. Biederman 	}
93db181ce0SEric W. Biederman }
94db181ce0SEric W. Biederman 
maybe_write_file(char * filename,char * fmt,...)95db86da7cSEric W. Biederman static void maybe_write_file(char *filename, char *fmt, ...)
96db86da7cSEric W. Biederman {
97db86da7cSEric W. Biederman 	va_list ap;
98db86da7cSEric W. Biederman 
99db86da7cSEric W. Biederman 	va_start(ap, fmt);
100db86da7cSEric W. Biederman 	vmaybe_write_file(true, filename, fmt, ap);
101db86da7cSEric W. Biederman 	va_end(ap);
102db86da7cSEric W. Biederman 
103db86da7cSEric W. Biederman }
104db86da7cSEric W. Biederman 
write_file(char * filename,char * fmt,...)105db86da7cSEric W. Biederman static void write_file(char *filename, char *fmt, ...)
106db86da7cSEric W. Biederman {
107db86da7cSEric W. Biederman 	va_list ap;
108db86da7cSEric W. Biederman 
109db86da7cSEric W. Biederman 	va_start(ap, fmt);
110db86da7cSEric W. Biederman 	vmaybe_write_file(false, filename, fmt, ap);
111db86da7cSEric W. Biederman 	va_end(ap);
112db86da7cSEric W. Biederman 
113db86da7cSEric W. Biederman }
114db86da7cSEric W. Biederman 
read_mnt_flags(const char * path)1154a44a19bSEric W. Biederman static int read_mnt_flags(const char *path)
1164a44a19bSEric W. Biederman {
1174a44a19bSEric W. Biederman 	int ret;
1184a44a19bSEric W. Biederman 	struct statvfs stat;
1194a44a19bSEric W. Biederman 	int mnt_flags;
1204a44a19bSEric W. Biederman 
1214a44a19bSEric W. Biederman 	ret = statvfs(path, &stat);
1224a44a19bSEric W. Biederman 	if (ret != 0) {
1234a44a19bSEric W. Biederman 		die("statvfs of %s failed: %s\n",
1244a44a19bSEric W. Biederman 			path, strerror(errno));
1254a44a19bSEric W. Biederman 	}
1264a44a19bSEric W. Biederman 	if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | \
1274a44a19bSEric W. Biederman 			ST_NOEXEC | ST_NOATIME | ST_NODIRATIME | ST_RELATIME | \
1284a44a19bSEric W. Biederman 			ST_SYNCHRONOUS | ST_MANDLOCK)) {
1294a44a19bSEric W. Biederman 		die("Unrecognized mount flags\n");
1304a44a19bSEric W. Biederman 	}
1314a44a19bSEric W. Biederman 	mnt_flags = 0;
1324a44a19bSEric W. Biederman 	if (stat.f_flag & ST_RDONLY)
1334a44a19bSEric W. Biederman 		mnt_flags |= MS_RDONLY;
1344a44a19bSEric W. Biederman 	if (stat.f_flag & ST_NOSUID)
1354a44a19bSEric W. Biederman 		mnt_flags |= MS_NOSUID;
1364a44a19bSEric W. Biederman 	if (stat.f_flag & ST_NODEV)
1374a44a19bSEric W. Biederman 		mnt_flags |= MS_NODEV;
1384a44a19bSEric W. Biederman 	if (stat.f_flag & ST_NOEXEC)
1394a44a19bSEric W. Biederman 		mnt_flags |= MS_NOEXEC;
1404a44a19bSEric W. Biederman 	if (stat.f_flag & ST_NOATIME)
1414a44a19bSEric W. Biederman 		mnt_flags |= MS_NOATIME;
1424a44a19bSEric W. Biederman 	if (stat.f_flag & ST_NODIRATIME)
1434a44a19bSEric W. Biederman 		mnt_flags |= MS_NODIRATIME;
1444a44a19bSEric W. Biederman 	if (stat.f_flag & ST_RELATIME)
1454a44a19bSEric W. Biederman 		mnt_flags |= MS_RELATIME;
1464a44a19bSEric W. Biederman 	if (stat.f_flag & ST_SYNCHRONOUS)
1474a44a19bSEric W. Biederman 		mnt_flags |= MS_SYNCHRONOUS;
1484a44a19bSEric W. Biederman 	if (stat.f_flag & ST_MANDLOCK)
1494a44a19bSEric W. Biederman 		mnt_flags |= ST_MANDLOCK;
1504a44a19bSEric W. Biederman 
1514a44a19bSEric W. Biederman 	return mnt_flags;
1524a44a19bSEric W. Biederman }
1534a44a19bSEric W. Biederman 
create_and_enter_userns(void)154db181ce0SEric W. Biederman static void create_and_enter_userns(void)
155db181ce0SEric W. Biederman {
156db181ce0SEric W. Biederman 	uid_t uid;
157db181ce0SEric W. Biederman 	gid_t gid;
158db181ce0SEric W. Biederman 
159db181ce0SEric W. Biederman 	uid = getuid();
160db181ce0SEric W. Biederman 	gid = getgid();
161db181ce0SEric W. Biederman 
162db181ce0SEric W. Biederman 	if (unshare(CLONE_NEWUSER) !=0) {
163db181ce0SEric W. Biederman 		die("unshare(CLONE_NEWUSER) failed: %s\n",
164db181ce0SEric W. Biederman 			strerror(errno));
165db181ce0SEric W. Biederman 	}
166db181ce0SEric W. Biederman 
167db86da7cSEric W. Biederman 	maybe_write_file("/proc/self/setgroups", "deny");
168db181ce0SEric W. Biederman 	write_file("/proc/self/uid_map", "0 %d 1", uid);
169db181ce0SEric W. Biederman 	write_file("/proc/self/gid_map", "0 %d 1", gid);
170db181ce0SEric W. Biederman 
171db181ce0SEric W. Biederman 	if (setgid(0) != 0) {
172db181ce0SEric W. Biederman 		die ("setgid(0) failed %s\n",
173db181ce0SEric W. Biederman 			strerror(errno));
174db181ce0SEric W. Biederman 	}
175db181ce0SEric W. Biederman 	if (setuid(0) != 0) {
176db181ce0SEric W. Biederman 		die("setuid(0) failed %s\n",
177db181ce0SEric W. Biederman 			strerror(errno));
178db181ce0SEric W. Biederman 	}
179db181ce0SEric W. Biederman }
180db181ce0SEric W. Biederman 
181db181ce0SEric W. Biederman static
test_unpriv_remount(const char * fstype,const char * mount_options,int mount_flags,int remount_flags,int invalid_flags)1824a44a19bSEric W. Biederman bool test_unpriv_remount(const char *fstype, const char *mount_options,
1834a44a19bSEric W. Biederman 			 int mount_flags, int remount_flags, int invalid_flags)
184db181ce0SEric W. Biederman {
185db181ce0SEric W. Biederman 	pid_t child;
186db181ce0SEric W. Biederman 
187db181ce0SEric W. Biederman 	child = fork();
188db181ce0SEric W. Biederman 	if (child == -1) {
189db181ce0SEric W. Biederman 		die("fork failed: %s\n",
190db181ce0SEric W. Biederman 			strerror(errno));
191db181ce0SEric W. Biederman 	}
192db181ce0SEric W. Biederman 	if (child != 0) { /* parent */
193db181ce0SEric W. Biederman 		pid_t pid;
194db181ce0SEric W. Biederman 		int status;
195db181ce0SEric W. Biederman 		pid = waitpid(child, &status, 0);
196db181ce0SEric W. Biederman 		if (pid == -1) {
197db181ce0SEric W. Biederman 			die("waitpid failed: %s\n",
198db181ce0SEric W. Biederman 				strerror(errno));
199db181ce0SEric W. Biederman 		}
200db181ce0SEric W. Biederman 		if (pid != child) {
201db181ce0SEric W. Biederman 			die("waited for %d got %d\n",
202db181ce0SEric W. Biederman 				child, pid);
203db181ce0SEric W. Biederman 		}
204db181ce0SEric W. Biederman 		if (!WIFEXITED(status)) {
205db181ce0SEric W. Biederman 			die("child did not terminate cleanly\n");
206db181ce0SEric W. Biederman 		}
207*6d425d7cSYang Guang 		return WEXITSTATUS(status) == EXIT_SUCCESS;
208db181ce0SEric W. Biederman 	}
209db181ce0SEric W. Biederman 
210db181ce0SEric W. Biederman 	create_and_enter_userns();
211db181ce0SEric W. Biederman 	if (unshare(CLONE_NEWNS) != 0) {
212db181ce0SEric W. Biederman 		die("unshare(CLONE_NEWNS) failed: %s\n",
213db181ce0SEric W. Biederman 			strerror(errno));
214db181ce0SEric W. Biederman 	}
215db181ce0SEric W. Biederman 
2164a44a19bSEric W. Biederman 	if (mount("testing", "/tmp", fstype, mount_flags, mount_options) != 0) {
2174a44a19bSEric W. Biederman 		die("mount of %s with options '%s' on /tmp failed: %s\n",
2184a44a19bSEric W. Biederman 		    fstype,
2194a44a19bSEric W. Biederman 		    mount_options? mount_options : "",
220db181ce0SEric W. Biederman 		    strerror(errno));
221db181ce0SEric W. Biederman 	}
222db181ce0SEric W. Biederman 
223db181ce0SEric W. Biederman 	create_and_enter_userns();
224db181ce0SEric W. Biederman 
225db181ce0SEric W. Biederman 	if (unshare(CLONE_NEWNS) != 0) {
226db181ce0SEric W. Biederman 		die("unshare(CLONE_NEWNS) failed: %s\n",
227db181ce0SEric W. Biederman 			strerror(errno));
228db181ce0SEric W. Biederman 	}
229db181ce0SEric W. Biederman 
230db181ce0SEric W. Biederman 	if (mount("/tmp", "/tmp", "none",
231db181ce0SEric W. Biederman 		  MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) {
232db181ce0SEric W. Biederman 		/* system("cat /proc/self/mounts"); */
233db181ce0SEric W. Biederman 		die("remount of /tmp failed: %s\n",
234db181ce0SEric W. Biederman 		    strerror(errno));
235db181ce0SEric W. Biederman 	}
236db181ce0SEric W. Biederman 
237db181ce0SEric W. Biederman 	if (mount("/tmp", "/tmp", "none",
238db181ce0SEric W. Biederman 		  MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) {
239db181ce0SEric W. Biederman 		/* system("cat /proc/self/mounts"); */
240db181ce0SEric W. Biederman 		die("remount of /tmp with invalid flags "
241db181ce0SEric W. Biederman 		    "succeeded unexpectedly\n");
242db181ce0SEric W. Biederman 	}
243db181ce0SEric W. Biederman 	exit(EXIT_SUCCESS);
244db181ce0SEric W. Biederman }
245db181ce0SEric W. Biederman 
test_unpriv_remount_simple(int mount_flags)246db181ce0SEric W. Biederman static bool test_unpriv_remount_simple(int mount_flags)
247db181ce0SEric W. Biederman {
2484a44a19bSEric W. Biederman 	return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, 0);
249db181ce0SEric W. Biederman }
250db181ce0SEric W. Biederman 
test_unpriv_remount_atime(int mount_flags,int invalid_flags)251db181ce0SEric W. Biederman static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
252db181ce0SEric W. Biederman {
2534a44a19bSEric W. Biederman 	return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags,
2544a44a19bSEric W. Biederman 				   invalid_flags);
2554a44a19bSEric W. Biederman }
2564a44a19bSEric W. Biederman 
test_priv_mount_unpriv_remount(void)2574a44a19bSEric W. Biederman static bool test_priv_mount_unpriv_remount(void)
2584a44a19bSEric W. Biederman {
2594a44a19bSEric W. Biederman 	pid_t child;
2604a44a19bSEric W. Biederman 	int ret;
2614a44a19bSEric W. Biederman 	const char *orig_path = "/dev";
2624a44a19bSEric W. Biederman 	const char *dest_path = "/tmp";
2634a44a19bSEric W. Biederman 	int orig_mnt_flags, remount_mnt_flags;
2644a44a19bSEric W. Biederman 
2654a44a19bSEric W. Biederman 	child = fork();
2664a44a19bSEric W. Biederman 	if (child == -1) {
2674a44a19bSEric W. Biederman 		die("fork failed: %s\n",
2684a44a19bSEric W. Biederman 			strerror(errno));
2694a44a19bSEric W. Biederman 	}
2704a44a19bSEric W. Biederman 	if (child != 0) { /* parent */
2714a44a19bSEric W. Biederman 		pid_t pid;
2724a44a19bSEric W. Biederman 		int status;
2734a44a19bSEric W. Biederman 		pid = waitpid(child, &status, 0);
2744a44a19bSEric W. Biederman 		if (pid == -1) {
2754a44a19bSEric W. Biederman 			die("waitpid failed: %s\n",
2764a44a19bSEric W. Biederman 				strerror(errno));
2774a44a19bSEric W. Biederman 		}
2784a44a19bSEric W. Biederman 		if (pid != child) {
2794a44a19bSEric W. Biederman 			die("waited for %d got %d\n",
2804a44a19bSEric W. Biederman 				child, pid);
2814a44a19bSEric W. Biederman 		}
2824a44a19bSEric W. Biederman 		if (!WIFEXITED(status)) {
2834a44a19bSEric W. Biederman 			die("child did not terminate cleanly\n");
2844a44a19bSEric W. Biederman 		}
285*6d425d7cSYang Guang 		return WEXITSTATUS(status) == EXIT_SUCCESS;
2864a44a19bSEric W. Biederman 	}
2874a44a19bSEric W. Biederman 
2884a44a19bSEric W. Biederman 	orig_mnt_flags = read_mnt_flags(orig_path);
2894a44a19bSEric W. Biederman 
2904a44a19bSEric W. Biederman 	create_and_enter_userns();
2914a44a19bSEric W. Biederman 	ret = unshare(CLONE_NEWNS);
2924a44a19bSEric W. Biederman 	if (ret != 0) {
2934a44a19bSEric W. Biederman 		die("unshare(CLONE_NEWNS) failed: %s\n",
2944a44a19bSEric W. Biederman 			strerror(errno));
2954a44a19bSEric W. Biederman 	}
2964a44a19bSEric W. Biederman 
2974a44a19bSEric W. Biederman 	ret = mount(orig_path, dest_path, "bind", MS_BIND | MS_REC, NULL);
2984a44a19bSEric W. Biederman 	if (ret != 0) {
2994a44a19bSEric W. Biederman 		die("recursive bind mount of %s onto %s failed: %s\n",
3004a44a19bSEric W. Biederman 			orig_path, dest_path, strerror(errno));
3014a44a19bSEric W. Biederman 	}
3024a44a19bSEric W. Biederman 
3034a44a19bSEric W. Biederman 	ret = mount(dest_path, dest_path, "none",
3044a44a19bSEric W. Biederman 		    MS_REMOUNT | MS_BIND | orig_mnt_flags , NULL);
3054a44a19bSEric W. Biederman 	if (ret != 0) {
3064a44a19bSEric W. Biederman 		/* system("cat /proc/self/mounts"); */
3074a44a19bSEric W. Biederman 		die("remount of /tmp failed: %s\n",
3084a44a19bSEric W. Biederman 		    strerror(errno));
3094a44a19bSEric W. Biederman 	}
3104a44a19bSEric W. Biederman 
3114a44a19bSEric W. Biederman 	remount_mnt_flags = read_mnt_flags(dest_path);
3124a44a19bSEric W. Biederman 	if (orig_mnt_flags != remount_mnt_flags) {
3134a44a19bSEric W. Biederman 		die("Mount flags unexpectedly changed during remount of %s originally mounted on %s\n",
3144a44a19bSEric W. Biederman 			dest_path, orig_path);
3154a44a19bSEric W. Biederman 	}
3164a44a19bSEric W. Biederman 	exit(EXIT_SUCCESS);
317db181ce0SEric W. Biederman }
318db181ce0SEric W. Biederman 
main(int argc,char ** argv)319db181ce0SEric W. Biederman int main(int argc, char **argv)
320db181ce0SEric W. Biederman {
3214a44a19bSEric W. Biederman 	if (!test_unpriv_remount_simple(MS_RDONLY)) {
322db181ce0SEric W. Biederman 		die("MS_RDONLY malfunctions\n");
323db181ce0SEric W. Biederman 	}
3244a44a19bSEric W. Biederman 	if (!test_unpriv_remount("devpts", "newinstance", MS_NODEV, MS_NODEV, 0)) {
325db181ce0SEric W. Biederman 		die("MS_NODEV malfunctions\n");
326db181ce0SEric W. Biederman 	}
3274a44a19bSEric W. Biederman 	if (!test_unpriv_remount_simple(MS_NOSUID)) {
328db181ce0SEric W. Biederman 		die("MS_NOSUID malfunctions\n");
329db181ce0SEric W. Biederman 	}
3304a44a19bSEric W. Biederman 	if (!test_unpriv_remount_simple(MS_NOEXEC)) {
331db181ce0SEric W. Biederman 		die("MS_NOEXEC malfunctions\n");
332db181ce0SEric W. Biederman 	}
3334a44a19bSEric W. Biederman 	if (!test_unpriv_remount_atime(MS_RELATIME,
3344a44a19bSEric W. Biederman 				       MS_NOATIME))
335db181ce0SEric W. Biederman 	{
336db181ce0SEric W. Biederman 		die("MS_RELATIME malfunctions\n");
337db181ce0SEric W. Biederman 	}
3384a44a19bSEric W. Biederman 	if (!test_unpriv_remount_atime(MS_STRICTATIME,
3394a44a19bSEric W. Biederman 				       MS_NOATIME))
340db181ce0SEric W. Biederman 	{
341db181ce0SEric W. Biederman 		die("MS_STRICTATIME malfunctions\n");
342db181ce0SEric W. Biederman 	}
3434a44a19bSEric W. Biederman 	if (!test_unpriv_remount_atime(MS_NOATIME,
3444a44a19bSEric W. Biederman 				       MS_STRICTATIME))
345db181ce0SEric W. Biederman 	{
3464a44a19bSEric W. Biederman 		die("MS_NOATIME malfunctions\n");
347db181ce0SEric W. Biederman 	}
3484a44a19bSEric W. Biederman 	if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME,
3494a44a19bSEric W. Biederman 				       MS_NOATIME))
350db181ce0SEric W. Biederman 	{
3514a44a19bSEric W. Biederman 		die("MS_RELATIME|MS_NODIRATIME malfunctions\n");
352db181ce0SEric W. Biederman 	}
3534a44a19bSEric W. Biederman 	if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME,
3544a44a19bSEric W. Biederman 				       MS_NOATIME))
355db181ce0SEric W. Biederman 	{
3564a44a19bSEric W. Biederman 		die("MS_STRICTATIME|MS_NODIRATIME malfunctions\n");
357db181ce0SEric W. Biederman 	}
3584a44a19bSEric W. Biederman 	if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME,
3594a44a19bSEric W. Biederman 				       MS_STRICTATIME))
360db181ce0SEric W. Biederman 	{
3614a44a19bSEric W. Biederman 		die("MS_NOATIME|MS_DIRATIME malfunctions\n");
362db181ce0SEric W. Biederman 	}
3634a44a19bSEric W. Biederman 	if (!test_unpriv_remount("ramfs", NULL, MS_STRICTATIME, 0, MS_NOATIME))
364db181ce0SEric W. Biederman 	{
365db181ce0SEric W. Biederman 		die("Default atime malfunctions\n");
366db181ce0SEric W. Biederman 	}
3674a44a19bSEric W. Biederman 	if (!test_priv_mount_unpriv_remount()) {
3684a44a19bSEric W. Biederman 		die("Mount flags unexpectedly changed after remount\n");
3694a44a19bSEric W. Biederman 	}
370db181ce0SEric W. Biederman 	return EXIT_SUCCESS;
371db181ce0SEric W. Biederman }
372