blob: cb10873e443831bb9cdd058e4e849a80a45815dc [file] [log] [blame]
robbiew1d89ad52006-01-31 15:12:47 +00001/*
2 * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * You should have received a copy of the GNU General Public License along
Wanlong Gaofed96412012-10-24 10:10:29 +080013 * with this program; if not, write the Free Software Foundation, Inc.,
14 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
robbiew1d89ad52006-01-31 15:12:47 +000015 *
16 */
DAN LI6dcafa72013-05-14 10:31:15 +080017
18/*
DAN LIa4d106d2013-07-08 13:17:23 +080019 * DESCRIPTION
robbiew1d89ad52006-01-31 15:12:47 +000020 * Check for basic mount(2) system call flags.
subrata_modak4bb656a2009-02-26 12:02:09 +000021 *
robbiew1d89ad52006-01-31 15:12:47 +000022 * Verify that mount(2) syscall passes for each flag setting and validate
23 * the flags
24 * 1) MS_RDONLY - mount read-only.
25 * 2) MS_NODEV - disallow access to device special files.
26 * 3) MS_NOEXEC - disallow program execution.
27 * 4) MS_SYNCHRONOUS - writes are synced at once.
28 * 5) MS_REMOUNT - alter flags of a mounted FS.
29 * 6) MS_NOSUID - ignore suid and sgid bits.
DAN LI59e542b2013-07-08 13:18:48 +080030 * 7) MS_NOATIME - do not update access times.
DAN LIa4d106d2013-07-08 13:17:23 +080031 */
robbiew1d89ad52006-01-31 15:12:47 +000032
vapier5b31d1b2006-08-21 06:46:26 +000033#ifndef _GNU_SOURCE
Wanlong Gao354ebb42012-12-07 10:10:04 +080034#define _GNU_SOURCE
vapier5b31d1b2006-08-21 06:46:26 +000035#endif
36
robbiew1d89ad52006-01-31 15:12:47 +000037#include <sys/types.h>
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -080038#include <sys/mount.h>
robbiew1d89ad52006-01-31 15:12:47 +000039#include <sys/stat.h>
40#include <sys/wait.h>
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -080041#include <assert.h>
42#include <errno.h>
robbiew1d89ad52006-01-31 15:12:47 +000043#include <fcntl.h>
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -080044#include <pwd.h>
vapier5b31d1b2006-08-21 06:46:26 +000045#include <unistd.h>
DAN LIa4d106d2013-07-08 13:17:23 +080046
robbiew1d89ad52006-01-31 15:12:47 +000047#include "test.h"
DAN LIa4d106d2013-07-08 13:17:23 +080048#include "safe_macros.h"
robbiew1d89ad52006-01-31 15:12:47 +000049
robbiew1d89ad52006-01-31 15:12:47 +000050static void setup(void);
51static void cleanup(void);
subrata_modak56207ce2009-03-23 13:35:39 +000052static int test_rwflag(int, int);
robbiew1d89ad52006-01-31 15:12:47 +000053
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020054char *TCID = "mount03";
DAN LI59e542b2013-07-08 13:18:48 +080055int TST_TOTAL = 7;
robbiew1d89ad52006-01-31 15:12:47 +000056
robbiew1d89ad52006-01-31 15:12:47 +000057#define TEMP_FILE "temp_file"
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -080058#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
DAN LI6dcafa72013-05-14 10:31:15 +080059#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
60 S_IXGRP|S_IROTH|S_IXOTH)
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -080061#define SUID_MODE (S_ISUID|S_IRUSR|S_IXUSR|S_IXGRP|S_IXOTH)
robbiew1d89ad52006-01-31 15:12:47 +000062
DAN LIa4d106d2013-07-08 13:17:23 +080063static const char mntpoint[] = "mntpoint";
Cyril Hrubis91416592014-08-13 14:37:49 +020064static const char *device;
65static const char *fs_type;
DAN LI6dcafa72013-05-14 10:31:15 +080066static int fildes;
robbiew1d89ad52006-01-31 15:12:47 +000067
DAN LI6dcafa72013-05-14 10:31:15 +080068static char write_buffer[BUFSIZ];
69static char read_buffer[BUFSIZ];
70static char path_name[PATH_MAX];
DAN LI6dcafa72013-05-14 10:31:15 +080071static char file[PATH_MAX];
robbiew1d89ad52006-01-31 15:12:47 +000072
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -080073long rwflags[] = {
74 MS_RDONLY,
75 MS_NODEV,
76 MS_NOEXEC,
77 MS_SYNCHRONOUS,
78 MS_RDONLY,
79 MS_NOSUID,
DAN LI59e542b2013-07-08 13:18:48 +080080 MS_NOATIME,
robbiew1d89ad52006-01-31 15:12:47 +000081};
82
DAN LI6dcafa72013-05-14 10:31:15 +080083int main(int argc, char *argv[])
robbiew1d89ad52006-01-31 15:12:47 +000084{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020085 int lc, i;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020086 const char *msg;
robbiew1d89ad52006-01-31 15:12:47 +000087
Cyril Hrubis91416592014-08-13 14:37:49 +020088 msg = parse_opts(argc, argv, NULL, NULL);
DAN LI6dcafa72013-05-14 10:31:15 +080089 if (msg != NULL)
robbiew1d89ad52006-01-31 15:12:47 +000090 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -080091
robbiew1d89ad52006-01-31 15:12:47 +000092 setup();
93
robbiew1d89ad52006-01-31 15:12:47 +000094 for (lc = 0; TEST_LOOPING(lc); lc++) {
95
Caspar Zhangd59a6592013-03-07 14:59:12 +080096 tst_count = 0;
robbiew1d89ad52006-01-31 15:12:47 +000097
subrata_modak56207ce2009-03-23 13:35:39 +000098 for (i = 0; i < TST_TOTAL; ++i) {
robbiew1d89ad52006-01-31 15:12:47 +000099
Cyril Hrubis91416592014-08-13 14:37:49 +0200100 TEST(mount(device, mntpoint, fs_type, rwflags[i],
DAN LI6dcafa72013-05-14 10:31:15 +0800101 NULL));
robbiew1d89ad52006-01-31 15:12:47 +0000102
robbiew1d89ad52006-01-31 15:12:47 +0000103 if (TEST_RETURN != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800104 tst_resm(TFAIL | TTERRNO, "mount(2) failed");
robbiew1d89ad52006-01-31 15:12:47 +0000105 continue;
106 }
107
108 /* Validate the rwflag */
DAN LI6dcafa72013-05-14 10:31:15 +0800109 if (test_rwflag(i, lc) == 1)
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800110 tst_resm(TFAIL, "mount(2) failed while"
Wanlong Gao354ebb42012-12-07 10:10:04 +0800111 " validating %ld", rwflags[i]);
DAN LI6dcafa72013-05-14 10:31:15 +0800112 else
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800113 tst_resm(TPASS, "mount(2) passed with "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 "rwflag = %ld", rwflags[i]);
DAN LI6dcafa72013-05-14 10:31:15 +0800115
Cyril Hrubisc60a2302015-01-29 16:28:24 +0100116 TEST(tst_umount(mntpoint));
DAN LI6dcafa72013-05-14 10:31:15 +0800117 if (TEST_RETURN != 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800118 tst_brkm(TBROK | TTERRNO, cleanup,
119 "umount(2) failed for %s", mntpoint);
Garrett Cooper2c282152010-12-16 00:55:50 -0800120 }
121 }
robbiew1d89ad52006-01-31 15:12:47 +0000122
robbiew1d89ad52006-01-31 15:12:47 +0000123 cleanup();
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800124 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800125}
robbiew1d89ad52006-01-31 15:12:47 +0000126
127/*
128 * test_rwflag(int i, int cnt)
129 * Validate the mount system call for rwflags.
130 */
subrata_modak56207ce2009-03-23 13:35:39 +0000131int test_rwflag(int i, int cnt)
robbiew1d89ad52006-01-31 15:12:47 +0000132{
DAN LI24324ad2013-05-14 10:40:28 +0800133 int ret, fd, pid, status;
robbiew1d89ad52006-01-31 15:12:47 +0000134 char nobody_uid[] = "nobody";
DAN LI59e542b2013-07-08 13:18:48 +0800135 time_t atime;
robbiew1d89ad52006-01-31 15:12:47 +0000136 struct passwd *ltpuser;
DAN LI59e542b2013-07-08 13:18:48 +0800137 struct stat file_stat;
robbiew1d89ad52006-01-31 15:12:47 +0000138
subrata_modak56207ce2009-03-23 13:35:39 +0000139 switch (i) {
140 case 0:
141 /* Validate MS_RDONLY flag of mount call */
robbiew1d89ad52006-01-31 15:12:47 +0000142
DAN LI6dcafa72013-05-14 10:31:15 +0800143 snprintf(file, PATH_MAX, "%stmp", path_name);
144 fd = open(file, O_CREAT | O_RDWR, S_IRWXU);
145 if (fd == -1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000146 if (errno == EROFS) {
147 return 0;
148 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800149 tst_resm(TWARN | TERRNO,
150 "open didn't fail with EROFS");
subrata_modak56207ce2009-03-23 13:35:39 +0000151 return 1;
152 }
153 }
154 close(fd);
155 return 1;
156 case 1:
157 /* Validate MS_NODEV flag of mount call */
158
DAN LI6dcafa72013-05-14 10:31:15 +0800159 snprintf(file, PATH_MAX, "%smynod_%d_%d", path_name, getpid(),
Wanlong Gao354ebb42012-12-07 10:10:04 +0800160 cnt);
subrata_modak56207ce2009-03-23 13:35:39 +0000161 if (mknod(file, S_IFBLK | 0777, 0) == 0) {
DAN LI6dcafa72013-05-14 10:31:15 +0800162 fd = open(file, O_RDWR, S_IRWXU);
163 if (fd == -1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000164 if (errno == EACCES) {
robbiew1d89ad52006-01-31 15:12:47 +0000165 return 0;
166 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 tst_resm(TWARN | TERRNO,
168 "open didn't fail with EACCES");
robbiew1d89ad52006-01-31 15:12:47 +0000169 return 1;
170 }
171 }
172 close(fd);
subrata_modak56207ce2009-03-23 13:35:39 +0000173 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800174 tst_resm(TWARN | TERRNO, "mknod(2) failed to create %s",
175 file);
robbiew1d89ad52006-01-31 15:12:47 +0000176 return 1;
subrata_modak56207ce2009-03-23 13:35:39 +0000177 }
178 return 1;
179 case 2:
180 /* Validate MS_NOEXEC flag of mount call */
robbiew1d89ad52006-01-31 15:12:47 +0000181
DAN LI6dcafa72013-05-14 10:31:15 +0800182 snprintf(file, PATH_MAX, "%stmp1", path_name);
183 fd = open(file, O_CREAT | O_RDWR, S_IRWXU);
184 if (fd == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800185 tst_resm(TWARN | TERRNO, "opening %s failed", file);
subrata_modak56207ce2009-03-23 13:35:39 +0000186 } else {
187 close(fd);
DAN LI24324ad2013-05-14 10:40:28 +0800188 ret = execlp(file, basename(file), NULL);
189 if ((ret == -1) && (errno == EACCES))
190 return 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000191 }
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800192 return 1;
subrata_modak56207ce2009-03-23 13:35:39 +0000193 case 3:
194 /*
195 * Validate MS_SYNCHRONOUS flag of mount call.
196 * Copy some data into data buffer.
197 */
robbiew1d89ad52006-01-31 15:12:47 +0000198
subrata_modak56207ce2009-03-23 13:35:39 +0000199 strcpy(write_buffer, "abcdefghijklmnopqrstuvwxyz");
200
201 /* Creat a temporary file under above directory */
DAN LI6dcafa72013-05-14 10:31:15 +0800202 snprintf(file, PATH_MAX, "%s%s", path_name, TEMP_FILE);
203 fildes = open(file, O_RDWR | O_CREAT, FILE_MODE);
204 if (fildes == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800205 tst_resm(TWARN | TERRNO,
206 "open(%s, O_RDWR|O_CREAT, %#o) failed",
207 file, FILE_MODE);
subrata_modak56207ce2009-03-23 13:35:39 +0000208 return 1;
209 }
210
211 /* Write the buffer data into file */
212 if (write(fildes, write_buffer, strlen(write_buffer)) !=
213 strlen(write_buffer)) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800214 tst_resm(TWARN | TERRNO, "writing to %s failed", file);
subrata_modak56207ce2009-03-23 13:35:39 +0000215 close(fildes);
216 return 1;
217 }
218
219 /* Set the file ptr to b'nning of file */
220 if (lseek(fildes, 0, SEEK_SET) < 0) {
221 tst_resm(TWARN, "lseek() failed on %s, error="
222 " %d", file, errno);
223 close(fildes);
224 return 1;
225 }
226
227 /* Read the contents of file */
228 if (read(fildes, read_buffer, sizeof(read_buffer)) > 0) {
229 if (strcmp(read_buffer, write_buffer)) {
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800230 tst_resm(TWARN, "Data read from %s and written "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800231 "mismatch", file);
subrata_modak56207ce2009-03-23 13:35:39 +0000232 close(fildes);
233 return 1;
234 } else {
235 close(fildes);
236 return 0;
237 }
238 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800239 tst_resm(TWARN | TERRNO, "read() Fails on %s", file);
subrata_modak56207ce2009-03-23 13:35:39 +0000240 close(fildes);
241 return 1;
242 }
243
244 case 4:
245 /* Validate MS_REMOUNT flag of mount call */
246
Cyril Hrubis91416592014-08-13 14:37:49 +0200247 TEST(mount(device, mntpoint, fs_type, MS_REMOUNT, NULL));
subrata_modak56207ce2009-03-23 13:35:39 +0000248 if (TEST_RETURN != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800249 tst_resm(TWARN | TTERRNO, "mount(2) failed to remount");
subrata_modak56207ce2009-03-23 13:35:39 +0000250 return 1;
251 } else {
DAN LI6dcafa72013-05-14 10:31:15 +0800252 snprintf(file, PATH_MAX, "%stmp2", path_name);
253 fd = open(file, O_CREAT | O_RDWR, S_IRWXU);
254 if (fd == -1) {
subrata_modak56207ce2009-03-23 13:35:39 +0000255 tst_resm(TWARN, "open(%s) on readonly "
256 "filesystem passed", file);
robbiew1d89ad52006-01-31 15:12:47 +0000257 return 1;
258 } else {
259 close(fd);
subrata_modak56207ce2009-03-23 13:35:39 +0000260 return 0;
robbiew1d89ad52006-01-31 15:12:47 +0000261 }
subrata_modak56207ce2009-03-23 13:35:39 +0000262 }
263 case 5:
264 /* Validate MS_NOSUID flag of mount call */
robbiew1d89ad52006-01-31 15:12:47 +0000265
DAN LIa4d106d2013-07-08 13:17:23 +0800266 snprintf(file, PATH_MAX, "%ssetuid_test", path_name);
267 SAFE_FILE_PRINTF(cleanup, file, "TEST FILE");
268
DAN LI59e542b2013-07-08 13:18:48 +0800269 if (stat(file, &file_stat) < 0)
DAN LIa4d106d2013-07-08 13:17:23 +0800270 tst_brkm(TBROK, cleanup, "stat for setuid_test failed");
271
DAN LI59e542b2013-07-08 13:18:48 +0800272 if (file_stat.st_mode != SUID_MODE &&
DAN LIa4d106d2013-07-08 13:17:23 +0800273 chmod(file, SUID_MODE) < 0)
274 tst_brkm(TBROK, cleanup,
275 "setuid for setuid_test failed");
276
DAN LI6dcafa72013-05-14 10:31:15 +0800277 pid = fork();
278 switch (pid) {
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800279 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800280 tst_resm(TBROK | TERRNO, "fork failed");
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800281 return 1;
282 case 0:
subrata_modak56207ce2009-03-23 13:35:39 +0000283 ltpuser = getpwnam(nobody_uid);
DAN LI6dcafa72013-05-14 10:31:15 +0800284 if (setreuid(ltpuser->pw_uid, ltpuser->pw_uid) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800285 tst_resm(TWARN | TERRNO,
286 "seteuid() failed to change euid to %d",
287 ltpuser->pw_uid);
DAN LI6dcafa72013-05-14 10:31:15 +0800288
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800289 execlp(file, basename(file), NULL);
290 exit(1);
291 default:
subrata_modak56207ce2009-03-23 13:35:39 +0000292 waitpid(pid, &status, 0);
293 if (WIFEXITED(status)) {
294 /* reset the setup_uid */
295 if (status)
296 return 0;
297 else
298 return 1;
299 }
300 }
DAN LI59e542b2013-07-08 13:18:48 +0800301 case 6:
302 /* Validate MS_NOATIME flag of mount call */
303
304 snprintf(file, PATH_MAX, "%satime", path_name);
305 fd = open(file, O_CREAT | O_RDWR, S_IRWXU);
306 if (fd == -1) {
307 tst_resm(TWARN | TERRNO, "opening %s failed", file);
308 return 1;
309 }
310
311 if (write(fd, "TEST_MS_NOATIME", 15) != 15) {
312 tst_resm(TWARN | TERRNO, "write %s failed", file);
313 return 1;
314 }
315
316 if (fstat(fd, &file_stat) == -1) {
317 tst_resm(TWARN | TERRNO, "stat %s failed #1", file);
318 return 1;
319 }
320
321 atime = file_stat.st_atime;
322
323 sleep(1);
324
325 if (read(fd, NULL, 20) == -1) {
326 tst_resm(TWARN | TERRNO, "read %s failed", file);
327 return 1;
328 }
329
330 if (fstat(fd, &file_stat) == -1) {
331 tst_resm(TWARN | TERRNO, "stat %s failed #2", file);
332 return 1;
333 }
334 close(fd);
335
336 if (file_stat.st_atime != atime) {
337 tst_resm(TWARN, "access time is updated");
338 return 1;
339 }
340 return 0;
robbiew1d89ad52006-01-31 15:12:47 +0000341 }
342 return 0;
343}
344
Cyril Hrubis629a1ac2013-08-08 17:24:04 +0200345static void setup(void)
robbiew1d89ad52006-01-31 15:12:47 +0000346{
DAN LI24324ad2013-05-14 10:40:28 +0800347 char path[PATH_MAX];
robbiew1d89ad52006-01-31 15:12:47 +0000348
robbiew1d89ad52006-01-31 15:12:47 +0000349 tst_sig(FORK, DEF_HANDLER, cleanup);
350
DAN LIa4d106d2013-07-08 13:17:23 +0800351 tst_require_root(NULL);
robbiew1d89ad52006-01-31 15:12:47 +0000352
robbiew1d89ad52006-01-31 15:12:47 +0000353 tst_tmpdir();
354
Cyril Hrubis91416592014-08-13 14:37:49 +0200355 fs_type = tst_dev_fs_type();
356 device = tst_acquire_device(cleanup);
357
358 if (!device)
359 tst_brkm(TCONF, cleanup, "Failed to obtain block device");
360
361 tst_mkfs(cleanup, device, fs_type, NULL);
362
DAN LIa4d106d2013-07-08 13:17:23 +0800363 SAFE_MKDIR(cleanup, mntpoint, DIR_MODE);
DAN LI24324ad2013-05-14 10:40:28 +0800364
DAN LI6dcafa72013-05-14 10:31:15 +0800365 if (getcwd(path_name, sizeof(path_name)) == NULL)
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800366 tst_brkm(TBROK, cleanup, "getcwd failed");
DAN LI6dcafa72013-05-14 10:31:15 +0800367
368 if (chmod(path_name, DIR_MODE) != 0)
Garrett Cooper2ddcc1b2010-12-13 20:47:00 -0800369 tst_brkm(TBROK, cleanup, "chmod(%s, %#o) failed",
DAN LI6dcafa72013-05-14 10:31:15 +0800370 path_name, DIR_MODE);
371
DAN LI24324ad2013-05-14 10:40:28 +0800372 strncpy(path, path_name, PATH_MAX);
373 snprintf(path_name, PATH_MAX, "%s/%s/", path, mntpoint);
robbiew1d89ad52006-01-31 15:12:47 +0000374
robbiew1d89ad52006-01-31 15:12:47 +0000375 TEST_PAUSE;
Garrett Cooper2c282152010-12-16 00:55:50 -0800376}
robbiew1d89ad52006-01-31 15:12:47 +0000377
Cyril Hrubis629a1ac2013-08-08 17:24:04 +0200378static void cleanup(void)
robbiew1d89ad52006-01-31 15:12:47 +0000379{
Cyril Hrubis91416592014-08-13 14:37:49 +0200380 if (device)
381 tst_release_device(NULL, device);
382
383 tst_rmdir();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700384}