aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2014-08-22 17:39:03 -0400
committerEric W. Biederman <ebiederm@xmission.com>2014-12-02 11:46:48 -0500
commit4a44a19b470a886997d6647a77bb3e38dcbfa8c5 (patch)
tree33ca998ebb8ddf4071eca23a2bb0a9472606ada0 /tools
parent3e1866410f11356a9fd869beb3e95983dc79c067 (diff)
mnt: Update unprivileged remount test
- MNT_NODEV should be irrelevant except when reading back mount flags, no longer specify MNT_NODEV on remount. - Test MNT_NODEV on devpts where it is meaningful even for unprivileged mounts. - Add a test to verify that remount of a prexisting mount with the same flags is allowed and does not change those flags. - Cleanup up the definitions of MS_REC, MS_RELATIME, MS_STRICTATIME that are used when the code is built in an environment without them. - Correct the test error messages when tests fail. There were not 5 tests that tested MS_RELATIME. Cc: stable@vger.kernel.org Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/mount/unprivileged-remount-test.c172
1 files changed, 142 insertions, 30 deletions
diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c
index 1b3ff2fda4d0..9669d375625a 100644
--- a/tools/testing/selftests/mount/unprivileged-remount-test.c
+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c
@@ -6,6 +6,8 @@
6#include <sys/types.h> 6#include <sys/types.h>
7#include <sys/mount.h> 7#include <sys/mount.h>
8#include <sys/wait.h> 8#include <sys/wait.h>
9#include <sys/vfs.h>
10#include <sys/statvfs.h>
9#include <stdlib.h> 11#include <stdlib.h>
10#include <unistd.h> 12#include <unistd.h>
11#include <fcntl.h> 13#include <fcntl.h>
@@ -32,11 +34,14 @@
32# define CLONE_NEWPID 0x20000000 34# define CLONE_NEWPID 0x20000000
33#endif 35#endif
34 36
37#ifndef MS_REC
38# define MS_REC 16384
39#endif
35#ifndef MS_RELATIME 40#ifndef MS_RELATIME
36#define MS_RELATIME (1 << 21) 41# define MS_RELATIME (1 << 21)
37#endif 42#endif
38#ifndef MS_STRICTATIME 43#ifndef MS_STRICTATIME
39#define MS_STRICTATIME (1 << 24) 44# define MS_STRICTATIME (1 << 24)
40#endif 45#endif
41 46
42static void die(char *fmt, ...) 47static void die(char *fmt, ...)
@@ -87,6 +92,45 @@ static void write_file(char *filename, char *fmt, ...)
87 } 92 }
88} 93}
89 94
95static int read_mnt_flags(const char *path)
96{
97 int ret;
98 struct statvfs stat;
99 int mnt_flags;
100
101 ret = statvfs(path, &stat);
102 if (ret != 0) {
103 die("statvfs of %s failed: %s\n",
104 path, strerror(errno));
105 }
106 if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | \
107 ST_NOEXEC | ST_NOATIME | ST_NODIRATIME | ST_RELATIME | \
108 ST_SYNCHRONOUS | ST_MANDLOCK)) {
109 die("Unrecognized mount flags\n");
110 }
111 mnt_flags = 0;
112 if (stat.f_flag & ST_RDONLY)
113 mnt_flags |= MS_RDONLY;
114 if (stat.f_flag & ST_NOSUID)
115 mnt_flags |= MS_NOSUID;
116 if (stat.f_flag & ST_NODEV)
117 mnt_flags |= MS_NODEV;
118 if (stat.f_flag & ST_NOEXEC)
119 mnt_flags |= MS_NOEXEC;
120 if (stat.f_flag & ST_NOATIME)
121 mnt_flags |= MS_NOATIME;
122 if (stat.f_flag & ST_NODIRATIME)
123 mnt_flags |= MS_NODIRATIME;
124 if (stat.f_flag & ST_RELATIME)
125 mnt_flags |= MS_RELATIME;
126 if (stat.f_flag & ST_SYNCHRONOUS)
127 mnt_flags |= MS_SYNCHRONOUS;
128 if (stat.f_flag & ST_MANDLOCK)
129 mnt_flags |= ST_MANDLOCK;
130
131 return mnt_flags;
132}
133
90static void create_and_enter_userns(void) 134static void create_and_enter_userns(void)
91{ 135{
92 uid_t uid; 136 uid_t uid;
@@ -118,7 +162,8 @@ static void create_and_enter_userns(void)
118} 162}
119 163
120static 164static
121bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) 165bool test_unpriv_remount(const char *fstype, const char *mount_options,
166 int mount_flags, int remount_flags, int invalid_flags)
122{ 167{
123 pid_t child; 168 pid_t child;
124 169
@@ -151,9 +196,11 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
151 strerror(errno)); 196 strerror(errno));
152 } 197 }
153 198
154 if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) { 199 if (mount("testing", "/tmp", fstype, mount_flags, mount_options) != 0) {
155 die("mount of /tmp failed: %s\n", 200 die("mount of %s with options '%s' on /tmp failed: %s\n",
156 strerror(errno)); 201 fstype,
202 mount_options? mount_options : "",
203 strerror(errno));
157 } 204 }
158 205
159 create_and_enter_userns(); 206 create_and_enter_userns();
@@ -181,62 +228,127 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
181 228
182static bool test_unpriv_remount_simple(int mount_flags) 229static bool test_unpriv_remount_simple(int mount_flags)
183{ 230{
184 return test_unpriv_remount(mount_flags, mount_flags, 0); 231 return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, 0);
185} 232}
186 233
187static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) 234static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
188{ 235{
189 return test_unpriv_remount(mount_flags, mount_flags, invalid_flags); 236 return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags,
237 invalid_flags);
238}
239
240static bool test_priv_mount_unpriv_remount(void)
241{
242 pid_t child;
243 int ret;
244 const char *orig_path = "/dev";
245 const char *dest_path = "/tmp";
246 int orig_mnt_flags, remount_mnt_flags;
247
248 child = fork();
249 if (child == -1) {
250 die("fork failed: %s\n",
251 strerror(errno));
252 }
253 if (child != 0) { /* parent */
254 pid_t pid;
255 int status;
256 pid = waitpid(child, &status, 0);
257 if (pid == -1) {
258 die("waitpid failed: %s\n",
259 strerror(errno));
260 }
261 if (pid != child) {
262 die("waited for %d got %d\n",
263 child, pid);
264 }
265 if (!WIFEXITED(status)) {
266 die("child did not terminate cleanly\n");
267 }
268 return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false;
269 }
270
271 orig_mnt_flags = read_mnt_flags(orig_path);
272
273 create_and_enter_userns();
274 ret = unshare(CLONE_NEWNS);
275 if (ret != 0) {
276 die("unshare(CLONE_NEWNS) failed: %s\n",
277 strerror(errno));
278 }
279
280 ret = mount(orig_path, dest_path, "bind", MS_BIND | MS_REC, NULL);
281 if (ret != 0) {
282 die("recursive bind mount of %s onto %s failed: %s\n",
283 orig_path, dest_path, strerror(errno));
284 }