17 # define CLONE_NEWNS 0x00020000
20 # define CLONE_NEWUTS 0x04000000
23 # define CLONE_NEWIPC 0x08000000
26 # define CLONE_NEWNET 0x40000000
29 # define CLONE_NEWUSER 0x10000000
32 # define CLONE_NEWPID 0x20000000
36 #define MS_RELATIME (1 << 21)
38 #ifndef MS_STRICTATIME
39 #define MS_STRICTATIME (1 << 24)
42 static void die(char *fmt, ...)
46 vfprintf(stderr, fmt, ap);
51 static void write_file(char *filename, char *fmt, ...)
60 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
63 die("vsnprintf failed: %s\n",
66 if (buf_len >= sizeof(buf)) {
67 die("vsnprintf output truncated\n");
70 fd = open(filename, O_WRONLY);
72 die("open of %s failed: %s\n",
73 filename, strerror(errno));
75 written = write(fd, buf, buf_len);
76 if (written != buf_len) {
78 die("short write to %s\n", filename);
80 die("write to %s failed: %s\n",
81 filename, strerror(errno));
85 die("close of %s failed: %s\n",
86 filename, strerror(errno));
90 static void create_and_enter_userns(void)
98 if (unshare(CLONE_NEWUSER) !=0) {
99 die("unshare(CLONE_NEWUSER) failed: %s\n",
103 write_file("/proc/self/uid_map", "0 %d 1", uid);
104 write_file("/proc/self/gid_map", "0 %d 1", gid);
106 if (setgroups(0, NULL) != 0) {
107 die("setgroups failed: %s\n",
110 if (setgid(0) != 0) {
111 die ("setgid(0) failed %s\n",
114 if (setuid(0) != 0) {
115 die("setuid(0) failed %s\n",
121 bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
127 die("fork failed: %s\n",
130 if (child != 0) { /* parent */
133 pid = waitpid(child, &status, 0);
135 die("waitpid failed: %s\n",
139 die("waited for %d got %d\n",
142 if (!WIFEXITED(status)) {
143 die("child did not terminate cleanly\n");
145 return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false;
148 create_and_enter_userns();
149 if (unshare(CLONE_NEWNS) != 0) {
150 die("unshare(CLONE_NEWNS) failed: %s\n",
154 if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) {
155 die("mount of /tmp failed: %s\n",
159 create_and_enter_userns();
161 if (unshare(CLONE_NEWNS) != 0) {
162 die("unshare(CLONE_NEWNS) failed: %s\n",
166 if (mount("/tmp", "/tmp", "none",
167 MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) {
168 /* system("cat /proc/self/mounts"); */
169 die("remount of /tmp failed: %s\n",
173 if (mount("/tmp", "/tmp", "none",
174 MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) {
175 /* system("cat /proc/self/mounts"); */
176 die("remount of /tmp with invalid flags "
177 "succeeded unexpectedly\n");
182 static bool test_unpriv_remount_simple(int mount_flags)
184 return test_unpriv_remount(mount_flags, mount_flags, 0);
187 static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
189 return test_unpriv_remount(mount_flags, mount_flags, invalid_flags);
192 int main(int argc, char **argv)
194 if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) {
195 die("MS_RDONLY malfunctions\n");
197 if (!test_unpriv_remount_simple(MS_NODEV)) {
198 die("MS_NODEV malfunctions\n");
200 if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) {
201 die("MS_NOSUID malfunctions\n");
203 if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) {
204 die("MS_NOEXEC malfunctions\n");
206 if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV,
207 MS_NOATIME|MS_NODEV))
209 die("MS_RELATIME malfunctions\n");
211 if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV,
212 MS_NOATIME|MS_NODEV))
214 die("MS_STRICTATIME malfunctions\n");
216 if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV,
217 MS_STRICTATIME|MS_NODEV))
219 die("MS_RELATIME malfunctions\n");
221 if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV,
222 MS_NOATIME|MS_NODEV))
224 die("MS_RELATIME malfunctions\n");
226 if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV,
227 MS_NOATIME|MS_NODEV))
229 die("MS_RELATIME malfunctions\n");
231 if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV,
232 MS_STRICTATIME|MS_NODEV))
234 die("MS_RELATIME malfunctions\n");
236 if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV,
237 MS_NOATIME|MS_NODEV))
239 die("Default atime malfunctions\n");