Branch data Line data Source code
1 : : #include <stdio.h>
2 : : #include <unistd.h>
3 : : #include <fcntl.h>
4 : : #include <sys/mman.h>
5 : : #include <sys/types.h>
6 : : #include <dirent.h>
7 : : #include <errno.h>
8 : : #include <sys/stat.h>
9 : : #include <string.h>
10 : : #include <stdlib.h>
11 : : #include <sys/mount.h>
12 : : #include <sys/types.h>
13 : : #include <sys/wait.h>
14 : :
15 : : #include "crtools.h"
16 : : #include "types.h"
17 : : #include "util.h"
18 : : #include "log.h"
19 : : #include "mount.h"
20 : : #include "proc_parse.h"
21 : : #include "image.h"
22 : :
23 : : #include "protobuf.h"
24 : : #include "protobuf/mnt.pb-c.h"
25 : :
26 : : static struct mount_info *mntinfo;
27 : : int mntns_root = -1;
28 : :
29 : 4 : int open_mount(unsigned int s_dev)
30 : : {
31 : : struct mount_info *i;
32 : :
33 [ + - ]: 42 : for (i = mntinfo; i != NULL; i = i->next)
34 [ + + ]: 38 : if (s_dev == i->s_dev)
35 : 4 : return open(i->mountpoint, O_RDONLY);
36 : :
37 : : return -ENOENT;
38 : : }
39 : :
40 : 214 : int collect_mount_info(void)
41 : : {
42 : 214 : pr_info("Collecting mountinfo\n");
43 : :
44 : 214 : mntinfo = parse_mountinfo(getpid());
45 [ - + ]: 214 : if (!mntinfo) {
46 : 0 : pr_err("Parsing mountinfo %d failed\n", getpid());
47 : 214 : return -1;
48 : : }
49 : :
50 : : return 0;
51 : : }
52 : :
53 : : static struct mount_info *mnt_find_by_id(struct mount_info *list, int id)
54 : : {
55 : : struct mount_info *m;
56 : :
57 [ + + ]: 1824 : for (m = list; m != NULL; m = m->next)
58 [ + + ]: 1605 : if (m->mnt_id == id)
59 : : return m;
60 : :
61 : : return NULL;
62 : : }
63 : :
64 : 219 : static struct mount_info *mnt_build_ids_tree(struct mount_info *list)
65 : : {
66 : 219 : struct mount_info *m, *root = NULL;
67 : :
68 : : /*
69 : : * Just resolve the mnt_id:parent_mnt_id relations
70 : : */
71 : :
72 : 219 : pr_debug("\tBuilding plain mount tree\n");
73 [ + + ]: 901 : for (m = list; m != NULL; m = m->next) {
74 : : struct mount_info *p;
75 : :
76 : 682 : pr_debug("\t\tWorking on %d->%d\n", m->mnt_id, m->parent_mnt_id);
77 : 1364 : p = mnt_find_by_id(list, m->parent_mnt_id);
78 [ + + ]: 682 : if (!p) {
79 : : /* This should be / */
80 [ + - ][ + - ]: 219 : if (root == NULL && !strcmp(m->mountpoint, "/")) {
[ + - ]
81 : 219 : root = m;
82 : 219 : continue;
83 : : }
84 : :
85 [ # # ]: 0 : pr_err("Mountpoint %d w/o parent %d found @%s (root %s)\n",
86 : : m->mnt_id, m->parent_mnt_id, m->mountpoint,
87 : : root ? "found" : "not found");
88 : 0 : return NULL;
89 : : }
90 : :
91 : 463 : m->parent = p;
92 : 463 : list_add_tail(&m->siblings, &p->children);
93 : : }
94 : :
95 [ - + ]: 219 : if (!root) {
96 : 0 : pr_err("No root found for tree\n");
97 : 219 : return NULL;
98 : : }
99 : :
100 : : return root;
101 : : }
102 : :
103 : : static int mnt_depth(struct mount_info *m)
104 : : {
105 : 701 : int depth = 0;
106 : : char *c;
107 : :
108 [ + + ][ + + ]: 5431 : for (c = m->mountpoint; *c != '\0'; c++)
109 [ + + ][ + + ]: 4730 : if (*c == '/')
110 : 1004 : depth++;
111 : :
112 : : return depth;
113 : : }
114 : :
115 : 682 : static void mnt_resort_siblings(struct mount_info *tree)
116 : : {
117 : : struct mount_info *m, *p;
118 : 682 : LIST_HEAD(list);
119 : :
120 : : /*
121 : : * Put siblings of each node in an order they can be (u)mounted
122 : : * I.e. if we have mounts on foo/bar/, foo/bar/foobar/ and foo/
123 : : * we should put them in the foo/bar/foobar/, foo/bar/, foo/ order.
124 : : * Otherwise we will not be able to (u)mount them in a sequence.
125 : : *
126 : : * Funny, but all we need for this is to sort them in the descending
127 : : * order of the amount of /-s in a path =)
128 : : *
129 : : * Use stupid insertion sort here, we're not expecting mount trees
130 : : * to contain hundreds (or more) elements.
131 : : */
132 : :
133 : 682 : pr_info("\tResorting siblings on %d\n", tree->mnt_id);
134 [ + + ]: 1145 : while (!list_empty(&tree->children)) {
135 : : int depth;
136 : :
137 : 463 : m = list_first_entry(&tree->children, struct mount_info, siblings);
138 : 463 : list_del(&m->siblings);
139 : :
140 : 926 : depth = mnt_depth(m);
141 [ + + ]: 464 : list_for_each_entry(p, &list, siblings)
142 [ + + ]: 238 : if (mnt_depth(p) <= depth)
143 : : break;
144 : :
145 : 463 : list_add(&m->siblings, &p->siblings);
146 : 463 : mnt_resort_siblings(m);
147 : : }
148 : :
149 : 682 : list_splice(&list, &tree->children);
150 : 682 : }
151 : :
152 : 682 : static void mnt_tree_show(struct mount_info *tree, int off)
153 : : {
154 : : struct mount_info *m;
155 : :
156 : 682 : pr_info("%*s[%s](%d->%d)\n", off, "",
157 : : tree->mountpoint, tree->mnt_id, tree->parent_mnt_id);
158 : :
159 [ + + ]: 1145 : list_for_each_entry(m, &tree->children, siblings)
160 : 463 : mnt_tree_show(m, off + 1);
161 : :
162 : 682 : pr_info("%*s<--\n", off, "");
163 : 682 : }
164 : :
165 : 219 : static struct mount_info *mnt_build_tree(struct mount_info *list)
166 : : {
167 : : struct mount_info *tree;
168 : :
169 : : /*
170 : : * Organize them in a sequence in which they can be mounted/umounted.
171 : : */
172 : :
173 : 219 : pr_info("Building mountpoints tree\n");
174 : 219 : tree = mnt_build_ids_tree(list);
175 [ + - ]: 219 : if (!tree)
176 : : return NULL;
177 : :
178 : 219 : mnt_resort_siblings(tree);
179 : 219 : pr_info("Done:\n");
180 : 219 : mnt_tree_show(tree, 0);
181 : 219 : return tree;
182 : : }
183 : :
184 : 2 : static DIR *open_mountpoint(struct mount_info *pm)
185 : : {
186 : : int fd, ret;
187 : : char path[PATH_MAX + 1];
188 : : struct stat st;
189 : : DIR *fdir;
190 : :
191 [ - + ]: 2 : if (!list_empty(&pm->children)) {
192 : 0 : pr_err("Something is mounted on top of %s\n", pm->fstype->name);
193 : : return NULL;
194 : : }
195 : :
196 : 2 : snprintf(path, sizeof(path), ".%s", pm->mountpoint);
197 : 2 : fd = openat(mntns_root, path, O_RDONLY);
198 [ - + ]: 2 : if (fd < 0) {
199 : 0 : pr_perror("Can't open %s", pm->mountpoint);
200 : : return NULL;
201 : : }
202 : :
203 : 2 : ret = fstat(fd, &st);
204 [ - + ]: 2 : if (ret < 0) {
205 : 0 : pr_perror("fstat(%s) failed", path);
206 : 0 : close(fd);
207 : : return NULL;
208 : : }
209 : :
210 [ - + ]: 2 : if (st.st_dev != pm->s_dev) {
211 : 0 : pr_err("The file system %#x %s %s is inaccessible\n",
212 : : pm->s_dev, pm->fstype->name, pm->mountpoint);
213 : 0 : close(fd);
214 : : return NULL;
215 : : }
216 : :
217 : 2 : fdir = fdopendir(fd);
218 [ - + ]: 2 : if (fdir == NULL) {
219 : 0 : close(fd);
220 : 2 : pr_perror("Can't open %s", pm->mountpoint);
221 : : return NULL;
222 : : }
223 : :
224 : : return fdir;
225 : : }
226 : :
227 : 2 : static int close_mountpoint(DIR *dfd)
228 : : {
229 [ - + ]: 2 : if (closedir(dfd)) {
230 : 0 : pr_perror("Unable to close directory");
231 : 2 : return -1;
232 : : }
233 : : return 0;
234 : : }
235 : :
236 : 1 : static int tmpfs_dump(struct mount_info *pm)
237 : : {
238 : 1 : int ret = -1;
239 : : char tmpfs_path[PATH_MAX];
240 : 1 : int fd, fd_img = -1;
241 : 1 : DIR *fdir = NULL;
242 : :
243 : 1 : fdir = open_mountpoint(pm);
244 [ + - ]: 1 : if (fdir == NULL)
245 : : return -1;
246 : :
247 : 1 : fd = dirfd(fdir);
248 [ - + ]: 1 : if (fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC) == -1) {
249 : 0 : pr_perror("Can not drop FD_CLOEXEC");
250 : 0 : goto out;
251 : : }
252 : :
253 : 1 : fd_img = open_image(CR_FD_TMPFS, O_DUMP, pm->mnt_id);
254 [ + - ]: 1 : if (fd_img < 0)
255 : : goto out;
256 : :
257 : 1 : snprintf(tmpfs_path, sizeof(tmpfs_path),
258 : : "/proc/self/fd/%d", fd);
259 : :
260 : 1 : ret = cr_system(-1, fd_img, -1, "tar", (char *[])
261 : 1 : { "tar", "--create",
262 : : "--gzip",
263 : : "--check-links",
264 : : "--preserve-permissions",
265 : : "--sparse",
266 : : "--numeric-owner",
267 : : "--directory", tmpfs_path, ".", NULL });
268 : :
269 [ - + ]: 1 : if (ret)
270 : 0 : pr_err("Can't dump tmpfs content\n");
271 : :
272 : : out:
273 : 1 : close_safe(&fd_img);
274 : 1 : close_mountpoint(fdir);
275 : : return ret;
276 : : }
277 : :
278 : 1 : static int tmpfs_restore(struct mount_info *pm)
279 : : {
280 : : int ret;
281 : : int fd_img;
282 : :
283 : 1 : fd_img = open_image_ro(CR_FD_TMPFS, pm->mnt_id);
284 [ + - ]: 1 : if (fd_img < 0)
285 : : return -1;
286 : :
287 : 1 : ret = cr_system(fd_img, -1, -1, "tar",
288 : 2 : (char *[]) {"tar", "--extract", "--gzip",
289 : 1 : "--directory", pm->mountpoint, NULL});
290 : 1 : close(fd_img);
291 : :
292 [ - + ]: 1 : if (ret) {
293 : 0 : pr_err("Can't restore tmpfs content\n");
294 : 1 : return -1;
295 : : }
296 : :
297 : : return 0;
298 : : }
299 : :
300 : 1 : static int binfmt_misc_dump(struct mount_info *pm)
301 : : {
302 : 1 : int ret = -1;
303 : : struct dirent *de;
304 : 1 : DIR *fdir = NULL;
305 : :
306 : 1 : fdir = open_mountpoint(pm);
307 [ + - ]: 1 : if (fdir == NULL)
308 : : return -1;
309 : :
310 [ + + ]: 5 : while ((de = readdir(fdir))) {
311 [ + + ]: 4 : if (dir_dots(de))
312 : 2 : continue;
313 [ + + ]: 2 : if (!strcmp(de->d_name, "register"))
314 : 1 : continue;
315 [ + - ]: 1 : if (!strcmp(de->d_name, "status"))
316 : 1 : continue;
317 : :
318 : 0 : pr_err("binfmt_misc isn't empty: %s\n", de->d_name);
319 : 4 : goto out;
320 : : }
321 : :
322 : : ret = 0;
323 : : out:
324 : 1 : close_mountpoint(fdir);
325 : 1 : return ret;
326 : : }
327 : :
328 : : static struct fstype fstypes[] = {
329 : : { "unsupported" },
330 : : { "proc" },
331 : : { "sysfs" },
332 : : { "devtmpfs" },
333 : : { "binfmt_misc", binfmt_misc_dump },
334 : : { "tmpfs", tmpfs_dump, tmpfs_restore },
335 : : { "devpts" },
336 : : };
337 : :
338 : 5466 : struct fstype *find_fstype_by_name(char *fst)
339 : : {
340 : : int i;
341 : :
342 : : /*
343 : : * This fn is required for two things.
344 : : * 1st -- to check supported filesystems (as just mounting
345 : : * anything is wrong, almost every fs has its own features)
346 : : * 2nd -- save some space in the image (since we scan all
347 : : * names anyway)
348 : : */
349 : :
350 [ + + ]: 39907 : for (i = 0; i < ARRAY_SIZE(fstypes); i++)
351 [ + + ]: 34441 : if (!strcmp(fstypes[i].name, fst))
352 : 1869 : return fstypes + i;
353 : :
354 : : return &fstypes[0];
355 : : }
356 : :
357 : : static u32 encode_fstype(struct fstype *fst)
358 : : {
359 : 234 : return fst - fstypes;
360 : : }
361 : :
362 : : static struct fstype *decode_fstype(u32 fst)
363 : : {
364 : :
365 [ + - ]: 657 : if (fst >= ARRAY_SIZE(fstypes))
366 : : return &fstypes[0];
367 : :
368 : 657 : return &fstypes[fst];
369 : : }
370 : :
371 : : static inline int is_root(char *p)
372 : : {
373 [ - + ][ + - ]: 516 : return p[0] == '/' && p[1] == '\0';
[ - + ][ + - ]
374 : : }
375 : :
376 : : static inline int is_root_mount(struct mount_info *mi)
377 : : {
378 : 77 : return is_root(mi->mountpoint);
379 : : }
380 : :
381 : 234 : static int dump_one_mountpoint(struct mount_info *pm, int fd)
382 : : {
383 : 234 : MntEntry me = MNT_ENTRY__INIT;
384 : :
385 : 234 : pr_info("\t%d: %x:%s @ %s\n", pm->mnt_id, pm->s_dev,
386 : : pm->root, pm->mountpoint);
387 : :
388 : 468 : me.fstype = encode_fstype(pm->fstype);
389 [ + - ][ + + ]: 234 : if (fstypes[me.fstype].dump && fstypes[me.fstype].dump(pm))
390 : : return -1;
391 : :
392 : 234 : me.mnt_id = pm->mnt_id;
393 : 234 : me.root_dev = pm->s_dev;
394 : 234 : me.parent_mnt_id = pm->parent_mnt_id;
395 : 234 : me.flags = pm->flags;
396 : 234 : me.root = pm->root;
397 : 234 : me.mountpoint = pm->mountpoint;
398 : 234 : me.source = pm->source;
399 : 234 : me.options = pm->options;
400 : :
401 [ + + ][ - + ]: 311 : if (!me.fstype && !is_root_mount(pm)) {
402 : 0 : pr_err("FS mnt %s dev %#x root %s unsupported\n",
403 : : pm->mountpoint, pm->s_dev, pm->root);
404 : : return -1;
405 : : }
406 : :
407 [ + - ]: 234 : if (pb_write_one(fd, &me, PB_MOUNTPOINTS))
408 : : return -1;
409 : :
410 : : return 0;
411 : : }
412 : :
413 : 77 : int dump_mnt_ns(int ns_pid, struct cr_fdset *fdset)
414 : : {
415 : : struct mount_info *pm;
416 : : int img_fd;
417 : :
418 : 77 : pm = parse_mountinfo(ns_pid);
419 [ - + ]: 77 : if (!pm) {
420 : 0 : pr_err("Can't parse %d's mountinfo\n", ns_pid);
421 : 77 : return -1;
422 : : }
423 : :
424 : 77 : pr_info("Dumping mountpoints\n");
425 : :
426 : 77 : img_fd = fdset_fd(fdset, CR_FD_MOUNTPOINTS);
427 : : do {
428 : 234 : struct mount_info *n = pm->next;
429 : :
430 [ + - ]: 234 : if (dump_one_mountpoint(pm, img_fd))
431 : : return -1;
432 : :
433 [ + - ]: 234 : xfree(pm);
434 : 234 : pm = n;
435 [ + + ]: 234 : } while (pm);
436 : :
437 : : return 0;
438 : : }
439 : :
440 : : #define MNT_TREE_WALK(_mi, _el, _fn_f, _fn_r) do { \
441 : : while (1) { \
442 : : if (_fn_f(_mi)) \
443 : : return -1; \
444 : : if (!list_empty(&_mi->children)) { \
445 : : _mi = list_entry(_mi->children._el, \
446 : : struct mount_info, siblings); \
447 : : continue; \
448 : : } \
449 : : up: \
450 : : if (_fn_r(_mi)) \
451 : : return -1; \
452 : : if (_mi->parent == NULL) \
453 : : return 0; \
454 : : if (_mi->siblings._el == &_mi->parent->children) { \
455 : : _mi = _mi->parent; \
456 : : goto up; \
457 : : } \
458 : : _mi = list_entry(_mi->siblings._el, \
459 : : struct mount_info, siblings); \
460 : : } \
461 : : } while (0)
462 : :
463 : : #define MNT_WALK_NONE 0 &&
464 : :
465 : :
466 : 657 : static int mnt_tree_for_each(struct mount_info *m,
467 : : int (*fn)(struct mount_info *))
468 : : {
469 [ + - ][ + + ]: 877 : MNT_TREE_WALK(m, next, fn, MNT_WALK_NONE);
[ + + ][ + + ]
470 : : }
471 : :
472 : 25 : static int mnt_tree_for_each_reverse(struct mount_info *m,
473 : : int (*fn)(struct mount_info *))
474 : : {
475 [ + + ][ + - ]: 30 : MNT_TREE_WALK(m, prev, MNT_WALK_NONE, fn);
[ + + ][ + + ]
476 : : }
477 : :
478 : 439 : static char *resolve_source(struct mount_info *mi)
479 : : {
480 [ + - ]: 439 : if (kdev_major(mi->s_dev) == 0)
481 : : /*
482 : : * Anonymous block device. Kernel creates them for
483 : : * diskless mounts.
484 : : */
485 : 439 : return mi->source;
486 : :
487 : 0 : pr_err("No device for %s mount\n", mi->mountpoint);
488 : 439 : return NULL;
489 : : }
490 : :
491 : 439 : static int do_new_mount(struct mount_info *mi)
492 : : {
493 : : char *src;
494 : 439 : struct fstype *tp = mi->fstype;
495 : :
496 : 439 : src = resolve_source(mi);
497 [ + - ]: 439 : if (!src)
498 : : return -1;
499 : :
500 [ - + ]: 439 : if (mount(src, mi->mountpoint, tp->name,
501 : 439 : mi->flags, mi->options) < 0) {
502 : 0 : pr_perror("Can't mount at %s", mi->mountpoint);
503 : 0 : return -1;
504 : : }
505 : :
506 [ + + ][ + - ]: 439 : if (tp->restore && tp->restore(mi))
507 : : return -1;
508 : :
509 : : return 0;
510 : : }
511 : :
512 : 0 : static int do_bind_mount(struct mount_info *mi)
513 : : {
514 : 0 : pr_err("No bind mounts at %s\n", mi->mountpoint);
515 : 0 : return -1;
516 : : }
517 : :
518 : : static inline int fsroot_mounted(struct mount_info *mi)
519 : : {
520 : 439 : return is_root(mi->root);
521 : : }
522 : :
523 : 657 : static int do_mount_one(struct mount_info *mi)
524 : : {
525 [ + + ]: 657 : if (!mi->parent)
526 : : return 0;
527 : :
528 : 439 : pr_debug("\tMounting %s @%s\n", mi->fstype->name, mi->mountpoint);
529 : :
530 [ + - ]: 439 : if (fsroot_mounted(mi))
531 : 439 : return do_new_mount(mi);
532 : : else
533 : 657 : return do_bind_mount(mi);
534 : : }
535 : :
536 : 25 : static int do_umount_one(struct mount_info *mi)
537 : : {
538 [ + + ]: 25 : if (!mi->parent)
539 : : return 0;
540 : :
541 [ - + ]: 24 : if (umount(mi->mountpoint)) {
542 : 0 : pr_perror("Can't umount at %s", mi->mountpoint);
543 : 0 : return -1;
544 : : }
545 : :
546 : 24 : pr_info("Umounted at %s\n", mi->mountpoint);
547 : 25 : return 0;
548 : : }
549 : :
550 : 1 : static int clean_mnt_ns(void)
551 : : {
552 : : int ret;
553 : : struct mount_info *pm;
554 : :
555 : 1 : pr_info("Cleaning mount namespace\n");
556 : :
557 : : /*
558 : : * Mountinfos were collected at prepare stage
559 : : */
560 : :
561 : 1 : pm = mnt_build_tree(mntinfo);
562 [ + - ]: 1 : if (!pm)
563 : : return -1;
564 : :
565 : 1 : ret = mnt_tree_for_each_reverse(pm, do_umount_one);
566 : :
567 [ + + ]: 26 : while (mntinfo) {
568 : 25 : pm = mntinfo->next;
569 [ + - ]: 25 : xfree(mntinfo);
570 : 25 : mntinfo = pm;
571 : : }
572 : :
573 : : return ret;
574 : : }
575 : :
576 : 217 : static int cr_pivot_root()
577 : : {
578 : 217 : char put_root[] = "crtools-put-root.XXXXXX";
579 : :
580 : 217 : pr_info("Move the root to %s", opts.root);
581 : :
582 [ - + ]: 217 : if (chdir(opts.root)) {
583 : 0 : pr_perror("chdir(%s) failed", opts.root);
584 : : return -1;
585 : : }
586 [ - + ]: 217 : if (mkdtemp(put_root) == NULL) {
587 : 0 : pr_perror("Can't create a temparary directory");
588 : : return -1;
589 : : }
590 [ - + ]: 217 : if (pivot_root(".", put_root)) {
591 : 0 : pr_perror("pivot_root(., %s) failed", put_root);
592 [ # # ]: 0 : if (rmdir(put_root))
593 : 0 : pr_perror("Can't remove the directory %s", put_root);
594 : : return -1;
595 : : }
596 [ - + ]: 217 : if (umount2(put_root, MNT_DETACH)) {
597 : 0 : pr_perror("Can't umount %s", put_root);
598 : : return -1;
599 : : }
600 [ - + ]: 217 : if (rmdir(put_root)) {
601 : 217 : pr_perror("Can't remove the directory %s", put_root);
602 : : return -1;
603 : : }
604 : :
605 : : return 0;
606 : : }
607 : :
608 : 218 : static int populate_mnt_ns(int ns_pid)
609 : : {
610 : 218 : MntEntry *me = NULL;
611 : : int img, ret;
612 : 218 : struct mount_info *pms = NULL;
613 : :
614 : 218 : pr_info("Populating mount namespace\n");
615 : :
616 : 218 : img = open_image_ro(CR_FD_MOUNTPOINTS, ns_pid);
617 [ + - ]: 218 : if (img < 0)
618 : : return -1;
619 : :
620 : 218 : pr_debug("Reading mountpoint images\n");
621 : :
622 : : while (1) {
623 : : struct mount_info *pm;
624 : :
625 : 875 : ret = pb_read_one_eof(img, &me, PB_MOUNTPOINTS);
626 [ + + ]: 875 : if (ret <= 0)
627 : : break;
628 : :
629 : 657 : ret = -1;
630 [ - + ]: 657 : pm = xmalloc(sizeof(*pm));
631 [ + - ]: 657 : if (!pm)
632 : : break;
633 : :
634 : : mnt_entry_init(pm);
635 : :
636 : 657 : pm->mnt_id = me->mnt_id;
637 : 657 : pm->parent_mnt_id = me->parent_mnt_id;
638 : 657 : pm->s_dev = me->root_dev;
639 : 657 : pm->flags = me->flags;
640 : :
641 : : /* FIXME: abort unsupported early */
642 : 1314 : pm->fstype = decode_fstype(me->fstype);
643 : :
644 : 657 : pr_debug("\t\tGetting root for %d\n", pm->mnt_id);
645 [ - + ]: 657 : pm->root = xstrdup(me->root);
646 [ + - ]: 657 : if (!pm->root)
647 : : goto err;
648 : :
649 : 657 : pr_debug("\t\tGetting mpt for %d\n", pm->mnt_id);
650 [ - + ]: 657 : pm->mountpoint = xstrdup(me->mountpoint);
651 [ + - ]: 657 : if (!pm->mountpoint)
652 : : goto err;
653 : :
654 : 657 : pr_debug("\t\tGetting source for %d\n", pm->mnt_id);
655 [ - + ]: 657 : pm->source = xstrdup(me->source);
656 [ + - ]: 657 : if (!pm->source)
657 : : goto err;
658 : :
659 : 657 : pr_debug("\t\tGetting opts for %d\n", pm->mnt_id);
660 [ - + ]: 657 : pm->options = xstrdup(me->options);
661 [ + - ]: 657 : if (!pm->options)
662 : : goto err;
663 : :
664 : 657 : pr_debug("\tRead %d mp @ %s\n", pm->mnt_id, pm->mountpoint);
665 : 657 : pm->next = pms;
666 : 657 : pms = pm;
667 : 657 : }
668 : :
669 [ - + ]: 218 : if (me)
670 : 0 : mnt_entry__free_unpacked(me, NULL);
671 : :
672 : 218 : close(img);
673 : 218 : mntinfo = pms;
674 : :
675 : 218 : pms = mnt_build_tree(pms);
676 [ + - ]: 218 : if (!pms)
677 : : return -1;
678 : :
679 : 218 : return mnt_tree_for_each(pms, do_mount_one);
680 : : err:
681 : 218 : close_safe(&img);
682 : : return -1;
683 : : }
684 : :
685 : 218 : int prepare_mnt_ns(int ns_pid)
686 : : {
687 : : int ret;
688 : :
689 : 218 : pr_info("Restoring mount namespace\n");
690 : :
691 : : /*
692 : : * The new mount namespace is filled with the mountpoint
693 : : * clones from the original one. We have to umount them
694 : : * prior to recreating new ones.
695 : : */
696 : :
697 [ + + ]: 218 : if (opts.root)
698 : 217 : ret = cr_pivot_root();
699 : : else
700 : 1 : ret = clean_mnt_ns();
701 : :
702 [ + - ]: 218 : if (!ret)
703 : 218 : ret = populate_mnt_ns(ns_pid);
704 : :
705 : 218 : return ret;
706 : : }
707 : :
708 : 0 : void show_mountpoints(int fd, struct cr_options *o)
709 : : {
710 : 0 : pb_show_plain(fd, PB_MOUNTPOINTS);
711 : 0 : }
712 : :
713 : 167 : int mntns_collect_root(pid_t pid)
714 : : {
715 : : int fd, pfd;
716 : : int ret;
717 : : char path[PATH_MAX + 1];
718 : :
719 : : /*
720 : : * If /proc/pid/root links on '/', it signs that a root of the task
721 : : * and a root of mntns is the same.
722 : : */
723 : :
724 : 167 : pfd = open_pid_proc(pid);
725 : 167 : ret = readlinkat(pfd, "root", path, sizeof(path) - 1);
726 [ + - ]: 167 : if (ret < 0)
727 : : return ret;
728 : :
729 : 167 : path[ret] = '\0';
730 : :
731 [ + - ][ - + ]: 167 : if (ret != 1 || path[0] != '/') {
732 : 0 : pr_err("The root task has another root than mntns: %s\n", path);
733 : 0 : close_pid_proc();
734 : : return -1;
735 : : }
736 : :
737 : 167 : fd = openat(pfd, "root", O_RDONLY | O_DIRECTORY, 0);
738 : 167 : close_pid_proc();
739 [ - + ]: 167 : if (fd < 0) {
740 : 0 : pr_perror("Can't open the task root");
741 : : return -1;
742 : : }
743 : :
744 : 167 : mntns_root = fd;
745 : :
746 : : return 0;
747 : 1140 : }
|