1 /*
2 * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
3 * AUTHOR: Nirmala Devi Dhanasekar <nirmala.devi@wipro.com>
4 * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20 /*
21
22 DESCRIPTION
23 Check for basic errors returned by mount(2) system call.
24
25 Verify that mount(2) returns -1 and sets errno to
26 1) ENODEV if filesystem type not configured
27 2) ENOTBLK if specialfile is not a block device
28 3) EBUSY if specialfile is already mounted or
29 it cannot be remounted read-only, because it still holds
30 files open for writing.
31 4) EINVAL if specialfile or device is invalid or
32 a remount was attempted, while source was not already
33 mounted on target.
34 5) EFAULT if specialfile or device file points to invalid address space.
35 6) ENAMETOOLONG if pathname was longer than MAXPATHLEN.
36 7) ENOENT if pathname was empty or has a nonexistent component.
37 8) ENOTDIR if not a directory.
38 */
39
40 #include <errno.h>
41 #include <sys/mount.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/fcntl.h>
45 #include "test.h"
46 #include "safe_macros.h"
47
48 static void setup(void);
49 static void cleanup(void);
50
51 char *TCID = "mount02";
52
53 #define DIR_MODE (S_IRWXU | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP)
54 #define FILE_MODE (S_IRWXU | S_IRWXG | S_IRWXO)
55
56 static char path[PATH_MAX + 2];
57 static const char *long_path = path;
58 static const char *fs_type;
59 static const char *wrong_fs_type = "error";
60 static const char *mntpoint = "mntpoint";
61 static const char *device;
62 static const char *null = NULL;
63 static const char *fault = (void*)-1;
64 static const char *nonexistent = "nonexistent";
65 static const char *char_dev = "char_device";
66 static const char *file = "filename";
67 static int fd;
68
69 static void do_umount(void);
70 static void close_umount(void);
71 static void do_mount(void);
72 static void mount_open(void);
73
74 static struct test_case {
75 const char **device;
76 const char **mntpoint;
77 const char **fs_type;
78 unsigned long flag;
79 int exp_errno;
80 void (*setup)(void);
81 void (*cleanup)(void);
82 } tc[] = {
83 {&device, &mntpoint, &wrong_fs_type, 0, ENODEV, NULL, NULL},
84 {&char_dev, &mntpoint, &fs_type, 0, ENOTBLK, NULL, NULL},
85 {&device, &mntpoint, &fs_type, 0, EBUSY, do_mount, do_umount},
86 {&device, &mntpoint, &fs_type, MS_REMOUNT | MS_RDONLY, EBUSY,
87 mount_open, close_umount},
88 {&null, &mntpoint, &fs_type, 0, EINVAL, NULL, NULL},
89 {&device, &mntpoint, &null, 0, EINVAL, NULL, NULL},
90 {&device, &mntpoint, &fs_type, MS_REMOUNT, EINVAL, NULL, NULL},
91 {&fault, &mntpoint, &fs_type, 0, EFAULT, NULL, NULL},
92 {&device, &mntpoint, &fault, 0, EFAULT, NULL, NULL},
93 {&device, &long_path, &fs_type, 0, ENAMETOOLONG, NULL, NULL},
94 {&device, &nonexistent, &fs_type, 0, ENOENT, NULL, NULL},
95 {&device, &file, &fs_type, 0, ENOTDIR, NULL, NULL},
96 };
97
98 int TST_TOTAL = ARRAY_SIZE(tc);
99
verify_mount(struct test_case * tc)100 static void verify_mount(struct test_case *tc)
101 {
102 if (tc->setup)
103 tc->setup();
104
105 TEST(mount(*tc->device, *tc->mntpoint, *tc->fs_type, tc->flag, NULL));
106
107 if (TEST_RETURN != -1) {
108 tst_resm(TFAIL, "mount() succeded unexpectedly (ret=%li)",
109 TEST_RETURN);
110 goto cleanup;
111 }
112
113 if (TEST_ERRNO != tc->exp_errno) {
114 tst_resm(TFAIL | TTERRNO,
115 "mount() was expected to fail with %s(%i)",
116 tst_strerrno(tc->exp_errno), tc->exp_errno);
117 goto cleanup;
118 }
119
120 tst_resm(TPASS | TTERRNO, "mount() failed expectedly");
121
122 cleanup:
123 if (tc->cleanup)
124 tc->cleanup();
125 }
126
main(int ac,char ** av)127 int main(int ac, char **av)
128 {
129 int lc, i;
130
131 tst_parse_opts(ac, av, NULL, NULL);
132
133 setup();
134
135 for (lc = 0; TEST_LOOPING(lc); lc++) {
136 tst_count = 0;
137
138 for (i = 0; i < TST_TOTAL; ++i)
139 verify_mount(tc + i);
140 }
141
142 cleanup();
143 tst_exit();
144 }
145
do_mount(void)146 static void do_mount(void)
147 {
148 if (mount(device, mntpoint, fs_type, 0, NULL))
149 tst_brkm(TBROK | TERRNO, cleanup, "Failed to mount(mntpoint)");
150 }
151
mount_open(void)152 static void mount_open(void)
153 {
154 do_mount();
155
156 fd = SAFE_OPEN(cleanup, "mntpoint/file", O_CREAT | O_RDWR, S_IRWXU);
157 }
158
close_umount(void)159 static void close_umount(void)
160 {
161 SAFE_CLOSE(cleanup, fd);
162 do_umount();
163 }
164
do_umount(void)165 static void do_umount(void)
166 {
167 if (tst_umount(mntpoint))
168 tst_brkm(TBROK | TERRNO, cleanup, "Failed to umount(mntpoint)");
169 }
170
setup(void)171 static void setup(void)
172 {
173 dev_t dev;
174
175 tst_sig(FORK, DEF_HANDLER, cleanup);
176
177 tst_require_root();
178
179 tst_tmpdir();
180
181 SAFE_TOUCH(cleanup, file, FILE_MODE, NULL);
182
183 fs_type = tst_dev_fs_type();
184 device = tst_acquire_device(cleanup);
185
186 if (!device)
187 tst_brkm(TCONF, cleanup, "Failed to obtain block device");
188
189 tst_mkfs(cleanup, device, fs_type, NULL, NULL);
190
191 SAFE_MKDIR(cleanup, mntpoint, DIR_MODE);
192
193 memset(path, 'a', PATH_MAX + 1);
194
195 dev = makedev(1, 3);
196 if (mknod(char_dev, S_IFCHR | FILE_MODE, dev)) {
197 tst_brkm(TBROK | TERRNO, cleanup,
198 "failed to mknod(char_dev, S_IFCHR | FILE_MODE, %lu)",
199 dev);
200 }
201
202 TEST_PAUSE;
203 }
204
cleanup(void)205 static void cleanup(void)
206 {
207 if (device)
208 tst_release_device(device);
209
210 tst_rmdir();
211 }
212