]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-mount-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2016 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/mount.h>
23 #include "alloc-util.h"
30 #include "mount-util.h"
31 #include "path-util.h"
33 #include "string-util.h"
35 static void test_mount_propagation_flags(const char *name
, int ret
, unsigned long expected
) {
38 assert_se(mount_propagation_flags_from_string(name
, &flags
) == ret
);
43 assert_se(flags
== expected
);
45 c
= mount_propagation_flags_to_string(flags
);
47 assert_se(isempty(c
));
49 assert_se(streq(c
, name
));
53 static void test_mnt_id(void) {
54 _cleanup_fclose_
FILE *f
= NULL
;
61 assert_se(f
= fopen("/proc/self/mountinfo", "re"));
62 assert_se(h
= hashmap_new(&trivial_hash_ops
));
65 _cleanup_free_
char *line
= NULL
, *path
= NULL
;
68 r
= read_line(f
, LONG_LINE_MAX
, &line
);
73 assert_se(sscanf(line
, "%i %*s %*s %*s %ms", &mnt_id
, &path
) == 2);
75 assert_se(hashmap_put(h
, INT_TO_PTR(mnt_id
), path
) >= 0);
79 HASHMAP_FOREACH_KEY(p
, k
, h
, i
) {
80 int mnt_id
= PTR_TO_INT(k
), mnt_id2
;
82 r
= path_get_mnt_id(p
, &mnt_id2
);
84 log_debug_errno(r
, "Failed to get the mnt id of %s: %m\n", p
);
88 log_debug("mnt id of %s is %i\n", p
, mnt_id2
);
90 if (mnt_id
== mnt_id2
)
93 /* The ids don't match? If so, then there are two mounts on the same path, let's check if that's really
95 assert_se(path_equal_ptr(hashmap_get(h
, INT_TO_PTR(mnt_id2
)), p
));
101 static void test_path_is_mount_point(void) {
103 char tmp_dir
[] = "/tmp/test-path-is-mount-point-XXXXXX";
104 _cleanup_free_
char *file1
= NULL
, *file2
= NULL
, *link1
= NULL
, *link2
= NULL
;
105 _cleanup_free_
char *dir1
= NULL
, *dir1file
= NULL
, *dirlink1
= NULL
, *dirlink1file
= NULL
;
106 _cleanup_free_
char *dir2
= NULL
, *dir2file
= NULL
;
108 assert_se(path_is_mount_point("/", NULL
, AT_SYMLINK_FOLLOW
) > 0);
109 assert_se(path_is_mount_point("/", NULL
, 0) > 0);
110 assert_se(path_is_mount_point("//", NULL
, AT_SYMLINK_FOLLOW
) > 0);
111 assert_se(path_is_mount_point("//", NULL
, 0) > 0);
113 assert_se(path_is_mount_point("/proc", NULL
, AT_SYMLINK_FOLLOW
) > 0);
114 assert_se(path_is_mount_point("/proc", NULL
, 0) > 0);
115 assert_se(path_is_mount_point("/proc/", NULL
, AT_SYMLINK_FOLLOW
) > 0);
116 assert_se(path_is_mount_point("/proc/", NULL
, 0) > 0);
118 assert_se(path_is_mount_point("/proc/1", NULL
, AT_SYMLINK_FOLLOW
) == 0);
119 assert_se(path_is_mount_point("/proc/1", NULL
, 0) == 0);
120 assert_se(path_is_mount_point("/proc/1/", NULL
, AT_SYMLINK_FOLLOW
) == 0);
121 assert_se(path_is_mount_point("/proc/1/", NULL
, 0) == 0);
123 assert_se(path_is_mount_point("/sys", NULL
, AT_SYMLINK_FOLLOW
) > 0);
124 assert_se(path_is_mount_point("/sys", NULL
, 0) > 0);
125 assert_se(path_is_mount_point("/sys/", NULL
, AT_SYMLINK_FOLLOW
) > 0);
126 assert_se(path_is_mount_point("/sys/", NULL
, 0) > 0);
128 /* we'll create a hierarchy of different kinds of dir/file/link
131 * <tmp>/file1, <tmp>/file2
132 * <tmp>/link1 -> file1, <tmp>/link2 -> file2
135 * <tmp>/dirlink1 -> dir1
136 * <tmp>/dirlink1file -> dirlink1/file
141 /* file mountpoints */
142 assert_se(mkdtemp(tmp_dir
) != NULL
);
143 file1
= path_join(NULL
, tmp_dir
, "file1");
145 file2
= path_join(NULL
, tmp_dir
, "file2");
147 fd
= open(file1
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
150 fd
= open(file2
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
153 link1
= path_join(NULL
, tmp_dir
, "link1");
155 assert_se(symlink("file1", link1
) == 0);
156 link2
= path_join(NULL
, tmp_dir
, "link2");
158 assert_se(symlink("file2", link2
) == 0);
160 assert_se(path_is_mount_point(file1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
161 assert_se(path_is_mount_point(file1
, NULL
, 0) == 0);
162 assert_se(path_is_mount_point(link1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
163 assert_se(path_is_mount_point(link1
, NULL
, 0) == 0);
165 /* directory mountpoints */
166 dir1
= path_join(NULL
, tmp_dir
, "dir1");
168 assert_se(mkdir(dir1
, 0755) == 0);
169 dirlink1
= path_join(NULL
, tmp_dir
, "dirlink1");
171 assert_se(symlink("dir1", dirlink1
) == 0);
172 dirlink1file
= path_join(NULL
, tmp_dir
, "dirlink1file");
173 assert_se(dirlink1file
);
174 assert_se(symlink("dirlink1/file", dirlink1file
) == 0);
175 dir2
= path_join(NULL
, tmp_dir
, "dir2");
177 assert_se(mkdir(dir2
, 0755) == 0);
179 assert_se(path_is_mount_point(dir1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
180 assert_se(path_is_mount_point(dir1
, NULL
, 0) == 0);
181 assert_se(path_is_mount_point(dirlink1
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
182 assert_se(path_is_mount_point(dirlink1
, NULL
, 0) == 0);
184 /* file in subdirectory mountpoints */
185 dir1file
= path_join(NULL
, dir1
, "file");
187 fd
= open(dir1file
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
191 assert_se(path_is_mount_point(dir1file
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
192 assert_se(path_is_mount_point(dir1file
, NULL
, 0) == 0);
193 assert_se(path_is_mount_point(dirlink1file
, NULL
, AT_SYMLINK_FOLLOW
) == 0);
194 assert_se(path_is_mount_point(dirlink1file
, NULL
, 0) == 0);
196 /* these tests will only work as root */
197 if (mount(file1
, file2
, NULL
, MS_BIND
, NULL
) >= 0) {
198 int rf
, rt
, rdf
, rdt
, rlf
, rlt
, rl1f
, rl1t
;
202 /* capture results in vars, to avoid dangling mounts on failure */
203 log_info("%s: %s", __func__
, file2
);
204 rf
= path_is_mount_point(file2
, NULL
, 0);
205 rt
= path_is_mount_point(file2
, NULL
, AT_SYMLINK_FOLLOW
);
207 file2d
= strjoina(file2
, "/");
208 log_info("%s: %s", __func__
, file2d
);
209 rdf
= path_is_mount_point(file2d
, NULL
, 0);
210 rdt
= path_is_mount_point(file2d
, NULL
, AT_SYMLINK_FOLLOW
);
212 log_info("%s: %s", __func__
, link2
);
213 rlf
= path_is_mount_point(link2
, NULL
, 0);
214 rlt
= path_is_mount_point(link2
, NULL
, AT_SYMLINK_FOLLOW
);
216 assert_se(umount(file2
) == 0);
220 assert_se(rdf
== -ENOTDIR
);
221 assert_se(rdt
== -ENOTDIR
);
226 dir2file
= path_join(NULL
, dir2
, "file");
228 fd
= open(dir2file
, O_WRONLY
|O_CREAT
|O_EXCL
|O_CLOEXEC
, 0664);
232 assert_se(mount(dir2
, dir1
, NULL
, MS_BIND
, NULL
) >= 0);
234 log_info("%s: %s", __func__
, dir1
);
235 rf
= path_is_mount_point(dir1
, NULL
, 0);
236 rt
= path_is_mount_point(dir1
, NULL
, AT_SYMLINK_FOLLOW
);
237 log_info("%s: %s", __func__
, dirlink1
);
238 rlf
= path_is_mount_point(dirlink1
, NULL
, 0);
239 rlt
= path_is_mount_point(dirlink1
, NULL
, AT_SYMLINK_FOLLOW
);
240 log_info("%s: %s", __func__
, dirlink1file
);
241 /* its parent is a mount point, but not /file itself */
242 rl1f
= path_is_mount_point(dirlink1file
, NULL
, 0);
243 rl1t
= path_is_mount_point(dirlink1file
, NULL
, AT_SYMLINK_FOLLOW
);
245 assert_se(umount(dir1
) == 0);
251 assert_se(rl1f
== 0);
252 assert_se(rl1t
== 0);
255 printf("Skipping bind mount file test: %m\n");
257 assert_se(rm_rf(tmp_dir
, REMOVE_ROOT
|REMOVE_PHYSICAL
) == 0);
260 static void test_mount_option_mangle(void) {
264 assert_se(mount_option_mangle(NULL
, MS_RDONLY
|MS_NOSUID
, &f
, &opts
) == 0);
265 assert_se(f
== (MS_RDONLY
|MS_NOSUID
));
266 assert_se(opts
== NULL
);
268 assert_se(mount_option_mangle("", MS_RDONLY
|MS_NOSUID
, &f
, &opts
) == 0);
269 assert_se(f
== (MS_RDONLY
|MS_NOSUID
));
270 assert_se(opts
== NULL
);
272 assert_se(mount_option_mangle("ro,nosuid,nodev,noexec", 0, &f
, &opts
) == 0);
273 assert_se(f
== (MS_RDONLY
|MS_NOSUID
|MS_NODEV
|MS_NOEXEC
));
274 assert_se(opts
== NULL
);
276 assert_se(mount_option_mangle("ro,nosuid,nodev,noexec,mode=755", 0, &f
, &opts
) == 0);
277 assert_se(f
== (MS_RDONLY
|MS_NOSUID
|MS_NODEV
|MS_NOEXEC
));
278 assert_se(streq(opts
, "mode=755"));
281 assert_se(mount_option_mangle("rw,nosuid,foo,hogehoge,nodev,mode=755", 0, &f
, &opts
) == 0);
282 assert_se(f
== (MS_NOSUID
|MS_NODEV
));
283 assert_se(streq(opts
, "foo,hogehoge,mode=755"));
286 assert_se(mount_option_mangle("rw,nosuid,nodev,noexec,relatime,net_cls,net_prio", MS_RDONLY
, &f
, &opts
) == 0);
287 assert_se(f
== (MS_NOSUID
|MS_NODEV
|MS_NOEXEC
|MS_RELATIME
));
288 assert_se(streq(opts
, "net_cls,net_prio"));
291 assert_se(mount_option_mangle("rw,nosuid,nodev,relatime,size=1630748k,mode=700,uid=1000,gid=1000", MS_RDONLY
, &f
, &opts
) == 0);
292 assert_se(f
== (MS_NOSUID
|MS_NODEV
|MS_RELATIME
));
293 assert_se(streq(opts
, "size=1630748k,mode=700,uid=1000,gid=1000"));
296 assert_se(mount_option_mangle("size=1630748k,rw,gid=1000,,,nodev,relatime,,mode=700,nosuid,uid=1000", MS_RDONLY
, &f
, &opts
) == 0);
297 assert_se(f
== (MS_NOSUID
|MS_NODEV
|MS_RELATIME
));
298 assert_se(streq(opts
, "size=1630748k,gid=1000,mode=700,uid=1000"));
301 assert_se(mount_option_mangle("rw,exec,size=8143984k,nr_inodes=2035996,mode=755", MS_RDONLY
|MS_NOSUID
|MS_NOEXEC
|MS_NODEV
, &f
, &opts
) == 0);
302 assert_se(f
== (MS_NOSUID
|MS_NODEV
));
303 assert_se(streq(opts
, "size=8143984k,nr_inodes=2035996,mode=755"));
306 assert_se(mount_option_mangle("rw,relatime,fmask=0022,,,dmask=0022", MS_RDONLY
, &f
, &opts
) == 0);
307 assert_se(f
== MS_RELATIME
);
308 assert_se(streq(opts
, "fmask=0022,dmask=0022"));
311 assert_se(mount_option_mangle("rw,relatime,fmask=0022,dmask=0022,\"hogehoge", MS_RDONLY
, &f
, &opts
) < 0);
314 int main(int argc
, char *argv
[]) {
316 log_set_max_level(LOG_DEBUG
);
318 test_mount_propagation_flags("shared", 0, MS_SHARED
);
319 test_mount_propagation_flags("slave", 0, MS_SLAVE
);
320 test_mount_propagation_flags("private", 0, MS_PRIVATE
);
321 test_mount_propagation_flags(NULL
, 0, 0);
322 test_mount_propagation_flags("", 0, 0);
323 test_mount_propagation_flags("xxxx", -EINVAL
, 0);
324 test_mount_propagation_flags(" ", -EINVAL
, 0);
327 test_path_is_mount_point();
328 test_mount_option_mangle();