LCOV - code coverage report
Current view: top level - home/snorch/criu - mount.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 447 750 59.6 %
Date: 2014-04-22 Functions: 47 55 85.5 %
Branches: 288 678 42.5 %

           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 "cr_options.h"
      16                 :            : #include "asm/types.h"
      17                 :            : #include "util.h"
      18                 :            : #include "util-pie.h"
      19                 :            : #include "log.h"
      20                 :            : #include "plugin.h"
      21                 :            : #include "mount.h"
      22                 :            : #include "pstree.h"
      23                 :            : #include "proc_parse.h"
      24                 :            : #include "image.h"
      25                 :            : #include "namespaces.h"
      26                 :            : #include "protobuf.h"
      27                 :            : #include "kerndat.h"
      28                 :            : #include "fs-magic.h"
      29                 :            : 
      30                 :            : #include "protobuf/mnt.pb-c.h"
      31                 :            : 
      32                 :            : /*
      33                 :            :  * Single linked list of mount points get from proc/images
      34                 :            :  */
      35                 :            : struct mount_info *mntinfo;
      36                 :            : 
      37                 :            : static int open_mountpoint(struct mount_info *pm);
      38                 :            : 
      39                 :            : static struct mount_info *mnt_build_tree(struct mount_info *list);
      40                 :            : static int validate_mounts(struct mount_info *info, bool call_plugins);
      41                 :            : 
      42                 :            : /* Asolute paths are used on dump and relative paths are used on restore */
      43                 :            : static inline int is_root(char *p)
      44                 :            : {
      45 [ +  - ][ +  - ]:       3774 :         return (!strcmp(p, "/"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
      46                 :            : }
      47                 :            : 
      48                 :            : /* True for the root mount (the topmost one) */
      49                 :            : static inline int is_root_mount(struct mount_info *mi)
      50                 :            : {
      51                 :            :         return is_root(mi->mountpoint + 1);
      52                 :            : }
      53                 :            : 
      54                 :            : /*
      55                 :            :  * True if the mountpoint target is root on its FS.
      56                 :            :  *
      57                 :            :  * This is used to determine whether we need to postpone
      58                 :            :  * mounting. E.g. one can bind mount some subdir from a
      59                 :            :  * disk, and in this case we'll have to get the root disk
      60                 :            :  * mount first, then bind-mount it. See do_mount_one().
      61                 :            :  */
      62                 :            : static inline int fsroot_mounted(struct mount_info *mi)
      63                 :            : {
      64                 :            :         return is_root(mi->root);
      65                 :            : }
      66                 :            : 
      67                 :            : static int __open_mountpoint(struct mount_info *pm, int mnt_fd);
      68                 :         52 : int open_mount(unsigned int s_dev)
      69                 :            : {
      70                 :            :         struct mount_info *i;
      71                 :            : 
      72         [ +  - ]:        800 :         for (i = mntinfo; i != NULL; i = i->next)
      73         [ +  + ]:        800 :                 if (s_dev == i->s_dev)
      74                 :         52 :                         return __open_mountpoint(i, -1);
      75                 :            : 
      76                 :            :         return -ENOENT;
      77                 :            : }
      78                 :            : 
      79                 :            : static struct mount_info *__lookup_mnt_id(struct mount_info *list, int id)
      80                 :            : {
      81                 :            :         struct mount_info *m;
      82                 :            : 
      83 [ #  # ][ #  # ]:    1916902 :         for (m = list; m != NULL; m = m->next)
         [ +  + ][ +  - ]
      84 [ #  # ][ #  # ]:    1913798 :                 if (m->mnt_id == id)
         [ +  + ][ +  + ]
      85                 :            :                         return m;
      86                 :            : 
      87                 :            :         return NULL;
      88                 :            : }
      89                 :            : 
      90                 :          4 : struct mount_info *lookup_mnt_id(unsigned int id)
      91                 :            : {
      92                 :          4 :         return __lookup_mnt_id(mntinfo, id);
      93                 :            : }
      94                 :            : 
      95                 :         50 : struct mount_info *lookup_mnt_sdev(unsigned int s_dev)
      96                 :            : {
      97                 :            :         struct mount_info *m;
      98                 :            : 
      99         [ +  - ]:        748 :         for (m = mntinfo; m != NULL; m = m->next)
     100         [ +  + ]:        748 :                 if (m->s_dev == s_dev)
     101                 :            :                         return m;
     102                 :            : 
     103                 :            :         return NULL;
     104                 :            : }
     105                 :            : 
     106                 :        308 : static struct mount_info *mount_resolve_path(struct mount_info *mntinfo_tree, const char *path)
     107                 :            : {
     108                 :        308 :         size_t pathlen = strlen(path);
     109                 :            :         struct mount_info *m = mntinfo_tree, *c;
     110                 :            : 
     111                 :            :         while (1) {
     112         [ +  + ]:       1180 :                 list_for_each_entry(c, &m->children, siblings) {
     113                 :            :                         size_t n;
     114                 :            : 
     115                 :        872 :                         n = strlen(c->mountpoint + 1);
     116         [ +  + ]:        872 :                         if (n > pathlen)
     117                 :        246 :                                 continue;
     118                 :            : 
     119         [ +  + ]:        626 :                         if (strncmp(c->mountpoint + 1, path, min(n, pathlen)))
     120                 :        408 :                                 continue;
     121 [ +  + ][ -  + ]:        218 :                         if (n < pathlen && path[n] != '/')
     122                 :          0 :                                 continue;
     123                 :            : 
     124                 :            :                         m = c;
     125                 :            :                         break;
     126                 :            :                 }
     127         [ +  + ]:        526 :                 if (&c->siblings == &m->children)
     128                 :            :                         break;
     129                 :            :         }
     130                 :            : 
     131                 :        308 :         pr_debug("Path `%s' resolved to `%s' mountpoint\n", path, m->mountpoint);
     132                 :        308 :         return m;
     133                 :            : }
     134                 :            : 
     135                 :        306 : dev_t phys_stat_resolve_dev(struct mount_info *tree,
     136                 :            :                                 dev_t st_dev, const char *path)
     137                 :            : {
     138                 :            :         struct mount_info *m;
     139                 :            : 
     140                 :        306 :         m = mount_resolve_path(tree, path);
     141                 :            :         /*
     142                 :            :          * BTRFS returns subvolume dev-id instead of
     143                 :            :          * superblock dev-id, in such case return device
     144                 :            :          * obtained from mountinfo (ie subvolume0).
     145                 :            :          */
     146                 :        612 :         return strcmp(m->fstype->name, "btrfs") ?
     147         [ +  - ]:        306 :                 MKKDEV(MAJOR(st_dev), MINOR(st_dev)) : m->s_dev;
     148                 :            : }
     149                 :            : 
     150                 :      18825 : bool phys_stat_dev_match(struct mount_info *tree, dev_t st_dev,
     151                 :            :                                 dev_t phys_dev, const char *path)
     152                 :            : {
     153         [ -  + ]:      18825 :         if (st_dev == kdev_to_odev(phys_dev))
     154                 :            :                 return true;
     155                 :            : 
     156                 :          0 :         return phys_dev == phys_stat_resolve_dev(tree, st_dev, path);
     157                 :            : }
     158                 :            : 
     159                 :            : /*
     160                 :            :  * Comparer two mounts. Return true if only mount points are differ.
     161                 :            :  * Don't care about root and mountpoints, if bind is true.
     162                 :            :  */
     163                 :    1063186 : static bool mounts_equal(struct mount_info* mi, struct mount_info *c, bool bind)
     164                 :            : {
     165 [ +  + ][ +  - ]:    1063186 :         if (mi->s_dev != c->s_dev ||
     166         [ +  - ]:        344 :             c->fstype != mi->fstype ||
     167         [ +  - ]:        344 :             strcmp(c->source, mi->source) ||
     168                 :        344 :             strcmp(c->options, mi->options))
     169                 :            :                 return false;
     170                 :            : 
     171         [ -  + ]:        344 :         if (bind)
     172                 :            :                 return true;
     173                 :            : 
     174         [ #  # ]:          0 :         if (strcmp(c->root, mi->root))
     175                 :            :                 return false;
     176         [ #  # ]:          0 :         if (strcmp(basename(c->mountpoint), basename(mi->mountpoint)))
     177                 :            :                 return false;
     178                 :          0 :         return true;
     179                 :            : }
     180                 :            : 
     181                 :       3104 : static struct mount_info *mnt_build_ids_tree(struct mount_info *list)
     182                 :            : {
     183                 :       3104 :         struct mount_info *m, *root = NULL;
     184                 :            : 
     185                 :            :         /*
     186                 :            :          * Just resolve the mnt_id:parent_mnt_id relations
     187                 :            :          */
     188                 :            : 
     189                 :       3104 :         pr_debug("\tBuilding plain mount tree\n");
     190         [ +  + ]:      76116 :         for (m = list; m != NULL; m = m->next) {
     191                 :            :                 struct mount_info *p;
     192                 :            : 
     193                 :      73012 :                 pr_debug("\t\tWorking on %d->%d\n", m->mnt_id, m->parent_mnt_id);
     194                 :      73012 :                 p = __lookup_mnt_id(list, m->parent_mnt_id);
     195         [ +  + ]:      73012 :                 if (!p) {
     196                 :            :                         /* This should be / */
     197 [ +  - ][ +  - ]:       6208 :                         if (root == NULL && is_root_mount(m)) {
     198                 :            :                                 root = m;
     199                 :       3104 :                                 continue;
     200                 :            :                         }
     201                 :            : 
     202         [ #  # ]:          0 :                         pr_err("Mountpoint %d w/o parent %d found @%s (root %s)\n",
     203                 :            :                                         m->mnt_id, m->parent_mnt_id, m->mountpoint,
     204                 :            :                                         root ? "found" : "not found");
     205 [ #  # ][ #  # ]:          0 :                         if (root && m->is_ns_root) {
     206 [ #  # ][ #  # ]:          0 :                                 if (!mounts_equal(root, m, true) ||
     207                 :          0 :                                                 strcmp(root->root, m->root)) {
     208                 :          0 :                                         pr_err("Nested mount namespaces with different roots are not supported yet");
     209                 :          0 :                                         return NULL;
     210                 :            :                                 }
     211                 :            : 
     212                 :            :                                 /*
     213                 :            :                                  * A root of a sub mount namespace is
     214                 :            :                                  * mounted in a temporary directory in the
     215                 :            :                                  * root mount namespace, so its parent is
     216                 :            :                                  * the main root.
     217                 :            :                                  */
     218                 :            :                                 p = root;
     219                 :            :                         } else
     220                 :            :                                 return NULL;
     221                 :            :                 }
     222                 :            : 
     223                 :      69908 :                 m->parent = p;
     224                 :      69908 :                 list_add_tail(&m->siblings, &p->children);
     225                 :            :         }
     226                 :            : 
     227         [ -  + ]:       3104 :         if (!root) {
     228                 :          0 :                 pr_err("No root found for tree\n");
     229                 :          0 :                 return NULL;
     230                 :            :         }
     231                 :            : 
     232                 :            :         return root;
     233                 :            : }
     234                 :            : 
     235                 :            : static int mnt_depth(struct mount_info *m)
     236                 :            : {
     237                 :            :         int depth = 0;
     238                 :            :         char *c;
     239                 :            : 
     240 [ +  + ][ +  + ]:    2312560 :         for (c = m->mountpoint; *c != '\0'; c++)
     241 [ +  + ][ +  + ]:    2186816 :                 if (*c == '/')
     242                 :     371936 :                         depth++;
     243                 :            : 
     244                 :            :         return depth;
     245                 :            : }
     246                 :            : 
     247                 :      73012 : static void mnt_resort_siblings(struct mount_info *tree)
     248                 :            : {
     249                 :     125744 :         struct mount_info *m, *p;
     250                 :      73012 :         LIST_HEAD(list);
     251                 :            : 
     252                 :            :         /*
     253                 :            :          * Put siblings of each node in an order they can be (u)mounted
     254                 :            :          * I.e. if we have mounts on foo/bar/, foo/bar/foobar/ and foo/
     255                 :            :          * we should put them in the foo/bar/foobar/, foo/bar/, foo/ order.
     256                 :            :          * Otherwise we will not be able to (u)mount them in a sequence.
     257                 :            :          *
     258                 :            :          * Funny, but all we need for this is to sort them in the descending
     259                 :            :          * order of the amount of /-s in a path =)
     260                 :            :          *
     261                 :            :          * Use stupid insertion sort here, we're not expecting mount trees
     262                 :            :          * to contain hundreds (or more) elements.
     263                 :            :          */
     264                 :            : 
     265                 :      73012 :         pr_info("\tResorting siblings on %d\n", tree->mnt_id);
     266         [ +  + ]:     142920 :         while (!list_empty(&tree->children)) {
     267                 :            :                 int depth;
     268                 :            : 
     269                 :      69908 :                 m = list_first_entry(&tree->children, struct mount_info, siblings);
     270                 :            :                 list_del(&m->siblings);
     271                 :            : 
     272                 :            :                 depth = mnt_depth(m);
     273         [ +  + ]:      77566 :                 list_for_each_entry(p, &list, siblings)
     274         [ +  + ]:      55836 :                         if (mnt_depth(p) <= depth)
     275                 :            :                                 break;
     276                 :            : 
     277                 :      69908 :                 list_add(&m->siblings, &p->siblings);
     278                 :      69908 :                 mnt_resort_siblings(m);
     279                 :            :         }
     280                 :            : 
     281                 :            :         list_splice(&list, &tree->children);
     282                 :      73012 : }
     283                 :            : 
     284                 :      73012 : static void mnt_tree_show(struct mount_info *tree, int off)
     285                 :            : {
     286                 :            :         struct mount_info *m;
     287                 :            : 
     288                 :      73012 :         pr_info("%*s[%s](%d->%d)\n", off, "",
     289                 :            :                         tree->mountpoint, tree->mnt_id, tree->parent_mnt_id);
     290                 :            : 
     291         [ +  + ]:     142920 :         list_for_each_entry(m, &tree->children, siblings)
     292                 :      69908 :                 mnt_tree_show(m, off + 1);
     293                 :            : 
     294                 :      73012 :         pr_info("%*s<--\n", off, "");
     295                 :      73012 : }
     296                 :            : 
     297                 :        212 : static int validate_mounts(struct mount_info *info, bool call_plugins)
     298                 :            : {
     299                 :        436 :         struct mount_info *m, *t;
     300                 :            : 
     301         [ +  + ]:        858 :         for (m = info; m; m = m->next) {
     302 [ +  + ][ -  + ]:        646 :                 if (m->parent && m->parent->shared_id) {
     303                 :            :                         struct mount_info *ct;
     304         [ #  # ]:          0 :                         if (list_empty(&m->parent->mnt_share))
     305                 :          0 :                                 continue;
     306                 :            :                         t = list_first_entry(&m->parent->mnt_share, struct mount_info, mnt_share);
     307                 :            : 
     308         [ #  # ]:          0 :                         list_for_each_entry(ct, &t->children, siblings) {
     309         [ #  # ]:          0 :                                 if (mounts_equal(m, ct, false))
     310                 :            :                                         break;
     311                 :            :                         }
     312         [ #  # ]:          0 :                         if (&ct->siblings == &t->children) {
     313                 :          0 :                                 pr_err("Two shared mounts %d, %d have different sets of children\n",
     314                 :            :                                         m->parent->mnt_id, t->mnt_id);
     315                 :          0 :                                 pr_err("%d:%s doesn't have a proper point for %d:%s\n",
     316                 :            :                                         t->mnt_id, t->mountpoint,
     317                 :            :                                         m->mnt_id, m->mountpoint);
     318                 :          0 :                                 return -1;
     319                 :            :                         }
     320                 :            :                 }
     321                 :            : 
     322 [ +  + ][ +  + ]:       1080 :                 if (m->parent && !fsroot_mounted(m)) {
     323         [ +  - ]:          2 :                         list_for_each_entry(t, &m->mnt_bind, mnt_bind) {
     324 [ +  - ][ -  + ]:          2 :                                 if (fsroot_mounted(t) || t->parent == NULL)
     325                 :            :                                         break;
     326                 :            :                         }
     327         [ -  + ]:          2 :                         if (&t->mnt_bind == &m->mnt_bind) {
     328                 :            :                                 int ret;
     329                 :            : 
     330         [ #  # ]:          0 :                                 if (call_plugins) {
     331                 :          0 :                                         ret = cr_plugin_dump_ext_mount(m->mountpoint + 1, m->mnt_id);
     332         [ #  # ]:          0 :                                         if (ret == 0)
     333                 :          0 :                                                 m->need_plugin = true;
     334         [ #  # ]:          0 :                                 } else if (m->need_plugin)
     335                 :            :                                         /* plugin should take care of this one */
     336                 :            :                                         ret = 0;
     337                 :            :                                 else
     338                 :            :                                         ret = -ENOTSUP;
     339         [ #  # ]:          0 :                                 if (ret < 0) {
     340         [ #  # ]:          0 :                                         if (ret == -ENOTSUP)
     341                 :          0 :                                                 pr_err("%d:%s doesn't have a proper root mount\n",
     342                 :            :                                                                 m->mnt_id, m->mountpoint);
     343                 :            :                                         return -1;
     344                 :            :                                 }
     345                 :            :                         }
     346                 :            :                 }
     347                 :            : 
     348         [ +  + ]:        646 :                 if (m->parent == NULL)
     349                 :        212 :                         continue;
     350                 :            : 
     351         [ +  + ]:       1316 :                 list_for_each_entry(t, &m->parent->children, siblings) {
     352                 :            :                         int tlen, mlen;
     353                 :            : 
     354         [ +  + ]:        882 :                         if (m == t)
     355                 :        434 :                                 continue;
     356                 :            : 
     357                 :        448 :                         tlen = strlen(t->mountpoint);
     358                 :        448 :                         mlen = strlen(m->mountpoint);
     359         [ +  + ]:        448 :                         if (mlen < tlen)
     360                 :        224 :                                 continue;
     361         [ +  - ]:        224 :                         if (strncmp(t->mountpoint, m->mountpoint, tlen))
     362                 :        224 :                                 continue;
     363 [ #  # ][ #  # ]:          0 :                         if (mlen > tlen && m->mountpoint[tlen] != '/')
     364                 :          0 :                                 continue;
     365                 :          0 :                         pr_err("%d:%s is overmounted\n", m->mnt_id, m->mountpoint);
     366                 :          0 :                         return -1;
     367                 :            :                 }
     368                 :            :         }
     369                 :            : 
     370                 :            :         return 0;
     371                 :            : }
     372                 :            : 
     373                 :       3104 : static int collect_shared(struct mount_info *info)
     374                 :            : {
     375                 :            :         struct mount_info *m, *t;
     376                 :            : 
     377                 :            :         /*
     378                 :            :          * If we have a shared mounts, both master
     379                 :            :          * slave targets are to be present in mount
     380                 :            :          * list, otherwise we can't be sure if we can
     381                 :            :          * recreate the scheme later on restore.
     382                 :            :          */
     383         [ +  + ]:      76116 :         for (m = info; m; m = m->next) {
     384                 :            :                 bool need_share, need_master;
     385                 :            : 
     386 [ -  + ][ #  # ]:      73012 :                 need_share = m->shared_id && list_empty(&m->mnt_share);
     387                 :      73012 :                 need_master = m->master_id;
     388                 :            : 
     389 [ +  - ][ -  + ]:      73012 :                 for (t = info; t && (need_share || need_master); t = t->next) {
     390         [ #  # ]:          0 :                         if (t == m)
     391                 :          0 :                                 continue;
     392 [ #  # ][ #  # ]:          0 :                         if (need_master && t->shared_id == m->master_id) {
     393                 :          0 :                                 pr_debug("The mount %d is slave for %d\n", m->mnt_id, t->mnt_id);
     394                 :          0 :                                 list_add(&m->mnt_slave, &t->mnt_slave_list);
     395                 :          0 :                                 m->mnt_master = t;
     396                 :            :                                 need_master = false;
     397                 :            :                         }
     398                 :            : 
     399                 :            :                         /* Collect all mounts from this group */
     400 [ #  # ][ #  # ]:          0 :                         if (need_share && t->shared_id == m->shared_id) {
     401                 :          0 :                                 pr_debug("Mount %d is shared with %d group %d\n",
     402                 :            :                                                 m->mnt_id, t->mnt_id, m->shared_id);
     403                 :          0 :                                 list_add(&t->mnt_share, &m->mnt_share);
     404                 :            :                         }
     405                 :            :                 }
     406                 :            : 
     407 [ -  + ][ #  # ]:      73012 :                 if (need_master && m->parent) {
     408                 :          0 :                         pr_err("Mount %d (master_id: %d shared_id: %d) "
     409                 :            :                                "has unreachable sharing\n", m->mnt_id,
     410                 :            :                                 m->master_id, m->shared_id);
     411                 :          0 :                         return -1;
     412                 :            :                 }
     413                 :            : 
     414                 :            :                 /* Search bind-mounts */
     415         [ +  + ]:      73012 :                 if (list_empty(&m->mnt_bind)) {
     416                 :            :                         /*
     417                 :            :                          * A first mounted point will be set up as a source point
     418                 :            :                          * for others. Look at propagate_mount()
     419                 :            :                          */
     420         [ +  + ]:    1135854 :                         for (t = m->next; t; t = t->next) {
     421         [ +  + ]:    1063186 :                                 if (mounts_equal(m, t, true))
     422                 :        344 :                                         list_add(&t->mnt_bind, &m->mnt_bind);
     423                 :            :                         }
     424                 :            :                 }
     425                 :            :         }
     426                 :            : 
     427                 :            :         return 0;
     428                 :            : }
     429                 :            : 
     430                 :       3104 : static struct mount_info *mnt_build_tree(struct mount_info *list)
     431                 :            : {
     432                 :            :         struct mount_info *tree;
     433                 :            : 
     434                 :            :         /*
     435                 :            :          * Organize them in a sequence in which they can be mounted/umounted.
     436                 :            :          */
     437                 :            : 
     438                 :       3104 :         pr_info("Building mountpoints tree\n");
     439                 :       3104 :         tree = mnt_build_ids_tree(list);
     440         [ +  - ]:       3104 :         if (!tree)
     441                 :            :                 return NULL;
     442                 :            : 
     443                 :       3104 :         mnt_resort_siblings(tree);
     444         [ +  - ]:       3104 :         if (collect_shared(list))
     445                 :            :                 return NULL;
     446                 :       3104 :         pr_info("Done:\n");
     447                 :       3104 :         mnt_tree_show(tree, 0);
     448                 :       3104 :         return tree;
     449                 :            : }
     450                 :            : 
     451                 :            : /*
     452                 :            :  * mnt_fd is a file descriptor on the mountpoint, which is closed in an error case.
     453                 :            :  * If mnt_fd is -1, the mountpoint will be opened by this function.
     454                 :            :  */
     455                 :        266 : static int __open_mountpoint(struct mount_info *pm, int mnt_fd)
     456                 :            : {
     457                 :            :         dev_t dev;
     458                 :            :         struct stat st;
     459                 :            :         int ret;
     460                 :            : 
     461         [ +  + ]:        266 :         if (mnt_fd == -1) {
     462                 :            :                 int mntns_root;
     463                 :            : 
     464                 :        264 :                 mntns_root = mntns_collect_root(pm->nsid->pid);
     465         [ +  - ]:        264 :                 if (mntns_root < 0)
     466                 :            :                         return -1;
     467                 :            : 
     468                 :        264 :                 mnt_fd = openat(mntns_root, pm->mountpoint, O_RDONLY);
     469         [ -  + ]:        264 :                 if (mnt_fd < 0) {
     470                 :          0 :                         pr_perror("Can't open %s", pm->mountpoint);
     471                 :          0 :                         return -1;
     472                 :            :                 }
     473                 :            :         }
     474                 :            : 
     475                 :            :         ret = fstat(mnt_fd, &st);
     476         [ -  + ]:        266 :         if (ret < 0) {
     477                 :          0 :                 pr_perror("fstat(%s) failed", pm->mountpoint);
     478                 :          0 :                 goto err;
     479                 :            :         }
     480                 :            : 
     481                 :        266 :         dev = phys_stat_resolve_dev(pm->nsid->mnt.mntinfo_tree, st.st_dev, pm->mountpoint + 1);
     482         [ -  + ]:        266 :         if (dev != pm->s_dev) {
     483                 :          0 :                 pr_err("The file system %#x (%#x) %s %s is inaccessible\n",
     484                 :            :                                 pm->s_dev, (int)dev, pm->fstype->name, pm->mountpoint);
     485                 :          0 :                 goto err;
     486                 :            :         }
     487                 :            : 
     488                 :            :         return mnt_fd;
     489                 :            : err:
     490                 :          0 :         close(mnt_fd);
     491                 :          0 :         return -1;
     492                 :            : }
     493                 :            : 
     494                 :        214 : static int open_mountpoint(struct mount_info *pm)
     495                 :            : {
     496                 :        214 :         int fd = -1, ns_old = -1;
     497                 :        214 :         char mnt_path[] = "/tmp/cr-tmpfs.XXXXXX";
     498                 :            : 
     499                 :            :         /*
     500                 :            :          * If a mount doesn't have children, we can open a mount point,
     501                 :            :          * otherwise we need to create a "private" copy.
     502                 :            :          */
     503         [ +  + ]:        214 :         if (list_empty(&pm->children))
     504                 :        212 :                 return __open_mountpoint(pm, -1);
     505                 :            : 
     506                 :          2 :         pr_info("Something is mounted on top of %s\n", pm->mountpoint);
     507                 :            : 
     508                 :            :         /*
     509                 :            :          * To create a "private" copy, the target mount is bind-mounted
     510                 :            :          * in a temporary place w/o MS_REC (non-recursively).
     511                 :            :          * A mount point can't be bind-mounted in criu's namespace, it will be
     512                 :            :          * mounted in a target namespace. The sequence of actions is
     513                 :            :          * mkdtemp, setns(tgt), mount, open, detach, setns(old).
     514                 :            :          */
     515                 :            : 
     516         [ +  - ]:          2 :         if (switch_ns(root_item->pid.real, &mnt_ns_desc, &ns_old) < 0)
     517                 :            :                 return -1;
     518                 :            : 
     519         [ -  + ]:          2 :         if (mkdtemp(mnt_path) == NULL) {
     520                 :          0 :                 pr_perror("Can't create a temporary directory");
     521                 :          0 :                 goto out;
     522                 :            :         }
     523                 :            : 
     524         [ -  + ]:          2 :         if (mount(pm->mountpoint, mnt_path, NULL, MS_BIND, NULL)) {
     525                 :          0 :                 pr_perror("Can't bind-mount %d:%s to %s",
     526                 :            :                                 pm->mnt_id, pm->mountpoint, mnt_path);
     527                 :          0 :                 rmdir(mnt_path);
     528                 :          0 :                 goto out;
     529                 :            :         }
     530                 :            : 
     531                 :          2 :         fd = open_detach_mount(mnt_path);
     532         [ +  - ]:          2 :         if (fd < 0)
     533                 :            :                 goto out;
     534                 :            : 
     535         [ -  + ]:          2 :         if (restore_ns(ns_old, &mnt_ns_desc)) {
     536                 :          0 :                 ns_old = -1;
     537                 :          0 :                 goto out;
     538                 :            :         }
     539                 :            : 
     540                 :          2 :         return __open_mountpoint(pm, fd);;
     541                 :            : out:
     542         [ #  # ]:          0 :         if (ns_old >= 0)
     543                 :          0 :                  restore_ns(ns_old, &mnt_ns_desc);
     544                 :          0 :         close_safe(&fd);
     545                 :          0 :         return -1;
     546                 :            : }
     547                 :            : 
     548                 :            : /* Is it mounted w or w/o the newinstance option */
     549                 :        210 : static int devpts_dump(struct mount_info *pm)
     550                 :            : {
     551                 :            :         static const char newinstance[] = ",newinstance";
     552                 :            :         struct stat *host_st;
     553                 :            :         struct stat st;
     554                 :            :         int fdir;
     555                 :            :         char *buf;
     556                 :            :         int len;
     557                 :            : 
     558                 :        210 :         host_st = kerndat_get_devpts_stat();
     559         [ +  - ]:        210 :         if (host_st == NULL)
     560                 :            :                 return -1;
     561                 :            : 
     562                 :        210 :         fdir = open_mountpoint(pm);
     563         [ +  - ]:        210 :         if (fdir < 0)
     564                 :            :                 return -1;
     565                 :            : 
     566         [ -  + ]:        210 :         if (fstat(fdir, &st)) {
     567                 :          0 :                 pr_perror("Unable to statfs %d:%s",
     568                 :            :                                 pm->mnt_id, pm->mountpoint);
     569                 :          0 :                 close(fdir);
     570                 :          0 :                 return -1;
     571                 :            :         }
     572                 :        210 :         close(fdir);
     573                 :            : 
     574         [ +  - ]:        210 :         if (host_st->st_dev == st.st_dev)
     575                 :            :                 return 0;
     576                 :            : 
     577                 :        210 :         len = strlen(pm->options);
     578         [ -  + ]:        210 :         buf = xrealloc(pm->options, len + sizeof(newinstance));
     579         [ +  - ]:        210 :         if (buf == NULL)
     580                 :            :                 return -1;
     581                 :            :         memcpy(buf, newinstance, sizeof(newinstance));
     582                 :            : 
     583                 :        210 :         pm->options = buf;
     584                 :            : 
     585                 :        210 :         return 0;
     586                 :            : }
     587                 :            : 
     588                 :          4 : static int tmpfs_dump(struct mount_info *pm)
     589                 :            : {
     590                 :            :         int ret = -1;
     591                 :            :         char tmpfs_path[PSFDS];
     592                 :          4 :         int fd = -1, fd_img = -1;
     593                 :            : 
     594                 :          4 :         fd = open_mountpoint(pm);
     595         [ +  - ]:          4 :         if (fd < 0)
     596                 :            :                 return -1;
     597                 :            : 
     598         [ -  + ]:          4 :         if (fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC) == -1) {
     599                 :          0 :                 pr_perror("Can not drop FD_CLOEXEC");
     600                 :          0 :                 goto out;
     601                 :            :         }
     602                 :            : 
     603                 :          4 :         fd_img = open_image(CR_FD_TMPFS_IMG, O_DUMP, pm->mnt_id);
     604         [ +  - ]:          4 :         if (fd_img < 0)
     605                 :            :                 goto out;
     606                 :            : 
     607                 :          4 :         sprintf(tmpfs_path, "/proc/self/fd/%d", fd);
     608                 :            : 
     609                 :          4 :         ret = cr_system(-1, fd_img, -1, "tar", (char *[])
     610                 :          4 :                         { "tar", "--create",
     611                 :            :                         "--gzip",
     612                 :            :                         "--one-file-system",
     613                 :            :                         "--check-links",
     614                 :            :                         "--preserve-permissions",
     615                 :            :                         "--sparse",
     616                 :            :                         "--numeric-owner",
     617                 :            :                         "--directory", tmpfs_path, ".", NULL });
     618                 :            : 
     619         [ -  + ]:          4 :         if (ret)
     620                 :          0 :                 pr_err("Can't dump tmpfs content\n");
     621                 :            : 
     622                 :            : out:
     623                 :          4 :         close_safe(&fd_img);
     624                 :          4 :         close_safe(&fd);
     625                 :          4 :         return ret;
     626                 :            : }
     627                 :            : 
     628                 :          4 : static int tmpfs_restore(struct mount_info *pm)
     629                 :            : {
     630                 :            :         int ret;
     631                 :            :         int fd_img;
     632                 :            : 
     633                 :          4 :         fd_img = open_image(CR_FD_TMPFS_IMG, O_RSTR, pm->mnt_id);
     634         [ +  - ]:          4 :         if (fd_img < 0)
     635                 :            :                 return -1;
     636                 :            : 
     637                 :          4 :         ret = cr_system(fd_img, -1, -1, "tar",
     638                 :          8 :                         (char *[]) {"tar", "--extract", "--gzip",
     639                 :          4 :                                 "--directory", pm->mountpoint, NULL});
     640                 :          2 :         close(fd_img);
     641                 :            : 
     642         [ -  + ]:          2 :         if (ret) {
     643                 :          0 :                 pr_err("Can't restore tmpfs content\n");
     644                 :          0 :                 return -1;
     645                 :            :         }
     646                 :            : 
     647                 :            :         return 0;
     648                 :            : }
     649                 :            : 
     650                 :          0 : static int binfmt_misc_dump(struct mount_info *pm)
     651                 :            : {
     652                 :            :         int fd, ret = -1;
     653                 :            :         struct dirent *de;
     654                 :            :         DIR *fdir = NULL;
     655                 :            : 
     656                 :          0 :         fd = open_mountpoint(pm);
     657         [ #  # ]:          0 :         if (fd < 0)
     658                 :            :                 return -1;
     659                 :            : 
     660                 :          0 :         fdir = fdopendir(fd);
     661         [ #  # ]:          0 :         if (fdir == NULL) {
     662                 :          0 :                 close(fd);
     663                 :          0 :                 return -1;
     664                 :            :         }
     665                 :            : 
     666         [ #  # ]:          0 :         while ((de = readdir(fdir))) {
     667         [ #  # ]:          0 :                 if (dir_dots(de))
     668                 :          0 :                         continue;
     669         [ #  # ]:          0 :                 if (!strcmp(de->d_name, "register"))
     670                 :          0 :                         continue;
     671         [ #  # ]:          0 :                 if (!strcmp(de->d_name, "status"))
     672                 :          0 :                         continue;
     673                 :            : 
     674                 :          0 :                 pr_err("binfmt_misc isn't empty: %s\n", de->d_name);
     675                 :          0 :                 goto out;
     676                 :            :         }
     677                 :            : 
     678                 :            :         ret = 0;
     679                 :            : out:
     680                 :          0 :         closedir(fdir);
     681                 :          0 :         return ret;
     682                 :            : }
     683                 :            : 
     684                 :            : static struct fstype fstypes[] = {
     685                 :            :         {
     686                 :            :                 .name = "unsupported",
     687                 :            :                 .code = FSTYPE__UNSUPPORTED,
     688                 :            :         }, {
     689                 :            :                 .name = "proc",
     690                 :            :                 .code = FSTYPE__PROC,
     691                 :            :         }, {
     692                 :            :                 .name = "sysfs",
     693                 :            :                 .code = FSTYPE__SYSFS,
     694                 :            :         }, {
     695                 :            :                 .name = "devtmpfs",
     696                 :            :                 .code = FSTYPE__DEVTMPFS,
     697                 :            :         }, {
     698                 :            :                 .name = "binfmt_misc",
     699                 :            :                 .code = FSTYPE__BINFMT_MISC,
     700                 :            :                 .dump = binfmt_misc_dump,
     701                 :            :         }, {
     702                 :            :                 .name = "tmpfs",
     703                 :            :                 .code = FSTYPE__TMPFS,
     704                 :            :                 .dump = tmpfs_dump,
     705                 :            :                 .restore = tmpfs_restore,
     706                 :            :         }, {
     707                 :            :                 .name = "devpts",
     708                 :            :                 .dump = devpts_dump,
     709                 :            :                 .code = FSTYPE__DEVPTS,
     710                 :            :         }, {
     711                 :            :                 .name = "simfs",
     712                 :            :                 .code = FSTYPE__SIMFS,
     713                 :            :         }, {
     714                 :            :                 .name = "btrfs",
     715                 :            :                 .code = FSTYPE__UNSUPPORTED,
     716                 :            :         }
     717                 :            : };
     718                 :            : 
     719                 :      73002 : struct fstype *find_fstype_by_name(char *fst)
     720                 :            : {
     721                 :            :         int i;
     722                 :            : 
     723                 :            :         /*
     724                 :            :          * This fn is required for two things.
     725                 :            :          * 1st -- to check supported filesystems (as just mounting
     726                 :            :          * anything is wrong, almost every fs has its own features)
     727                 :            :          * 2nd -- save some space in the image (since we scan all
     728                 :            :          * names anyway)
     729                 :            :          */
     730                 :            : 
     731         [ +  + ]:     612140 :         for (i = 0; i < ARRAY_SIZE(fstypes); i++)
     732         [ +  + ]:     563454 :                 if (!strcmp(fstypes[i].name, fst))
     733                 :      24316 :                         return fstypes + i;
     734                 :            : 
     735                 :            :         return &fstypes[0];
     736                 :            : }
     737                 :            : 
     738                 :            : static struct fstype *decode_fstype(u32 fst)
     739                 :            : {
     740                 :            :         int i;
     741                 :            : 
     742         [ +  + ]:         10 :         if (fst == FSTYPE__UNSUPPORTED)
     743                 :            :                 goto uns;
     744                 :            : 
     745         [ +  - ]:         42 :         for (i = 0; i < ARRAY_SIZE(fstypes); i++)
     746         [ +  + ]:         42 :                 if (fstypes[i].code == fst)
     747                 :          8 :                         return fstypes + i;
     748                 :            : uns:
     749                 :            :         return &fstypes[0];
     750                 :            : }
     751                 :            : 
     752                 :        636 : static int dump_one_mountpoint(struct mount_info *pm, int fd)
     753                 :            : {
     754                 :        636 :         MntEntry me = MNT_ENTRY__INIT;
     755                 :            : 
     756                 :        636 :         pr_info("\t%d: %x:%s @ %s\n", pm->mnt_id, pm->s_dev,
     757                 :            :                         pm->root, pm->mountpoint);
     758                 :            : 
     759                 :        636 :         me.fstype               = pm->fstype->code;
     760 [ +  + ][ +  + ]:        848 :         if ((me.fstype == FSTYPE__UNSUPPORTED) && !is_root_mount(pm)) {
     761                 :            :                 struct mount_info *t;
     762                 :            : 
     763                 :            :                 /* Is it a bind-mount of the root mount */
     764         [ +  - ]:          2 :                 list_for_each_entry(t, &pm->mnt_bind, mnt_bind)
     765         [ -  + ]:          2 :                         if (t->parent == NULL)
     766                 :            :                                 break;
     767                 :            : 
     768 [ +  - ][ -  + ]:          2 :                 if (&t->mnt_bind == &pm->mnt_bind ||
     769                 :          2 :                     strlen(t->source) > strlen(pm->source)) {
     770                 :          0 :                         pr_err("FS mnt %s dev %#x root %s unsupported\n",
     771                 :            :                                         pm->mountpoint, pm->s_dev, pm->root);
     772                 :          0 :                         return -1;
     773                 :            :                 }
     774                 :            :         }
     775                 :            : 
     776 [ +  - ][ +  + ]:        636 :         if (!pm->need_plugin && pm->fstype->dump && pm->fstype->dump(pm))
                 [ +  - ]
     777                 :            :                 return -1;
     778                 :            : 
     779                 :        636 :         me.mnt_id               = pm->mnt_id;
     780                 :        636 :         me.root_dev             = pm->s_dev;
     781                 :        636 :         me.parent_mnt_id        = pm->parent_mnt_id;
     782                 :        636 :         me.flags                = pm->flags;
     783                 :        636 :         me.root                 = pm->root;
     784                 :        636 :         me.mountpoint           = pm->mountpoint + 1;
     785                 :        636 :         me.source               = pm->source;
     786                 :        636 :         me.options              = pm->options;
     787                 :        636 :         me.shared_id            = pm->shared_id;
     788                 :        636 :         me.has_shared_id        = true;
     789                 :        636 :         me.master_id            = pm->master_id;
     790                 :        636 :         me.has_master_id        = true;
     791         [ -  + ]:        636 :         if (pm->need_plugin) {
     792                 :          0 :                 me.has_with_plugin = true;
     793                 :          0 :                 me.with_plugin = true;
     794                 :            :         }
     795                 :            : 
     796         [ +  - ]:        636 :         if (pb_write_one(fd, &me, PB_MNT))
     797                 :            :                 return -1;
     798                 :            : 
     799                 :        636 :         return 0;
     800                 :            : }
     801                 :            : 
     802                 :       3102 : struct mount_info *collect_mntinfo(struct ns_id *ns)
     803                 :            : {
     804                 :            :         struct mount_info *pm, *p;
     805                 :            : 
     806         [ +  - ]:       3102 :         if (mntns_collect_root(ns->pid) < 0)
     807                 :            :                 return NULL;
     808                 :            : 
     809                 :       3102 :         pm = parse_mountinfo(ns->pid, ns);
     810         [ -  + ]:       3102 :         if (!pm) {
     811                 :          0 :                 pr_err("Can't parse %d's mountinfo\n", ns->pid);
     812                 :          0 :                 return NULL;
     813                 :            :         }
     814                 :            : 
     815                 :       3102 :         ns->mnt.mntinfo_tree = mnt_build_tree(pm);
     816         [ -  + ]:       3102 :         if (ns->mnt.mntinfo_tree == NULL)
     817                 :            :                 goto err;
     818                 :            : 
     819                 :            :         return pm;
     820                 :            : err:
     821         [ #  # ]:          0 :         while (pm) {
     822                 :            :                 p = pm;
     823                 :          0 :                 pm = pm->next;
     824         [ #  # ]:          0 :                 xfree(p);
     825                 :            :         }
     826                 :            : 
     827                 :          0 :         ns->mnt.mntinfo_tree = NULL;
     828                 :            : 
     829                 :          0 :         return NULL;
     830                 :            : }
     831                 :            : 
     832                 :        210 : int dump_mnt_ns(struct ns_id *ns)
     833                 :            : {
     834                 :            :         struct mount_info *pm, *pms;
     835                 :            :         int img_fd = -1, ret = -1;
     836                 :        210 :         int ns_id = ns->id;
     837                 :            : 
     838                 :        210 :         pms = collect_mntinfo(ns);
     839         [ +  - ]:        210 :         if (pms == NULL)
     840                 :            :                 goto err;
     841                 :            : 
     842         [ +  - ]:        210 :         if (validate_mounts(pms, true))
     843                 :            :                 goto err;
     844                 :            : 
     845                 :        210 :         pr_info("Dumping mountpoints\n");
     846                 :            : 
     847                 :        210 :         img_fd = open_image(CR_FD_MNTS, O_DUMP, ns_id);
     848         [ +  - ]:        210 :         if (img_fd < 0)
     849                 :            :                 goto err;
     850                 :            : 
     851         [ +  + ]:        846 :         for (pm = pms; pm; pm = pm->next)
     852         [ +  - ]:        636 :                 if (dump_one_mountpoint(pm, img_fd))
     853                 :            :                         goto err;
     854                 :            : 
     855         [ +  - ]:        210 :         if (mntinfo == NULL)
     856                 :        210 :                 mntinfo = pms;
     857                 :            :         else {
     858         [ #  # ]:          0 :                 for (pm = mntinfo; pm->next != NULL; pm = pm->next);
     859                 :            : 
     860                 :          0 :                 pm->next = pms;
     861                 :            :         }
     862                 :            :         ret = 0;
     863                 :            : err:
     864                 :        210 :         close(img_fd);
     865                 :        210 :         return ret;
     866                 :            : }
     867                 :            : 
     868                 :            : /*
     869                 :            :  * _fn_f  - pre-order traversal function
     870                 :            :  * _fn_f  - post-order traversal function
     871                 :            :  * _plist - a postpone list. _el is added to this list, if _fn_f returns
     872                 :            :  *          a positive value, and all lower elements are not enumirated.
     873                 :            :  */
     874                 :            : #define MNT_TREE_WALK(_r, _el, _fn_f, _fn_r, _plist, _prgs) do {                \
     875                 :            :                 struct mount_info *_mi = _r;                                    \
     876                 :            :                                                                                 \
     877                 :            :                 while (1) {                                                     \
     878                 :            :                         int ret;                                                \
     879                 :            :                                                                                 \
     880                 :            :                         list_del_init(&_mi->postpone);                           \
     881                 :            :                                                                                 \
     882                 :            :                         ret = _fn_f(_mi);                                       \
     883                 :            :                         if (ret < 0)                                         \
     884                 :            :                                 return -1;                                      \
     885                 :            :                         else if (ret > 0) {                                  \
     886                 :            :                                 list_add_tail(&_mi->postpone, _plist);           \
     887                 :            :                                 goto up;                                        \
     888                 :            :                         }                                                       \
     889                 :            :                                                                                 \
     890                 :            :                         _prgs++;                                        \
     891                 :            :                                                                                 \
     892                 :            :                         if (!list_empty(&_mi->children)) {                       \
     893                 :            :                                 _mi = list_entry(_mi->children._el,          \
     894                 :            :                                                 struct mount_info, siblings);   \
     895                 :            :                                 continue;                                       \
     896                 :            :                         }                                                       \
     897                 :            :         up:                                                                     \
     898                 :            :                         if (_fn_r(_mi))                                         \
     899                 :            :                                 return -1;                                      \
     900                 :            :                         if (_mi == _r)                                          \
     901                 :            :                                 break;                                          \
     902                 :            :                         if (_mi->siblings._el == &_mi->parent->children) { \
     903                 :            :                                 _mi = _mi->parent;                           \
     904                 :            :                                 goto up;                                        \
     905                 :            :                         }                                                       \
     906                 :            :                         _mi = list_entry(_mi->siblings._el,                  \
     907                 :            :                                         struct mount_info, siblings);           \
     908                 :            :                 }                                                               \
     909                 :            :         } while (0)
     910                 :            : 
     911                 :            : #define MNT_WALK_NONE   0 &&
     912                 :            : 
     913                 :            : 
     914                 :          2 : static int mnt_tree_for_each(struct mount_info *start,
     915                 :            :                 int (*fn)(struct mount_info *))
     916                 :            : {
     917                 :            :         struct mount_info *tmp;
     918                 :          2 :         LIST_HEAD(postpone);
     919                 :          2 :         LIST_HEAD(postpone2);
     920                 :            :         int progress;
     921                 :            : 
     922                 :          2 :         pr_debug("Start with %d:%s\n", start->mnt_id, start->mountpoint);
     923                 :          2 :         list_add(&start->postpone, &postpone);
     924                 :            : 
     925                 :            : again:
     926                 :            :         progress = 0;
     927                 :            : 
     928         [ +  - ]:          8 :         list_for_each_entry_safe(start, tmp, &postpone, postpone)
     929 [ +  - ][ -  + ]:          8 :                 MNT_TREE_WALK(start, next, fn, MNT_WALK_NONE, &postpone2, progress);
         [ +  + ][ +  - ]
                 [ -  + ]
     930                 :            : 
     931         [ #  # ]:          0 :         if (!progress) {
     932                 :            :                 struct mount_info *m;
     933                 :            : 
     934                 :          0 :                 pr_err("A few mount points can't be mounted");
     935         [ #  # ]:          0 :                 list_for_each_entry(m, &postpone2, postpone) {
     936                 :          0 :                         pr_err("%d:%d %s %s %s\n", m->mnt_id,
     937                 :            :                                 m->parent_mnt_id, m->root,
     938                 :            :                                 m->mountpoint, m->source);
     939                 :            :                 }
     940                 :            :                 return -1;
     941                 :            :         }
     942                 :            : 
     943                 :            :         list_splice_init(&postpone2, &postpone);
     944                 :            : 
     945         [ #  # ]:          0 :         if (!list_empty(&postpone))
     946                 :            :                 goto again;
     947                 :            : 
     948                 :            :         return 0;
     949                 :            : 
     950                 :            : }
     951                 :            : 
     952                 :          0 : static int mnt_tree_for_each_reverse(struct mount_info *m,
     953                 :            :                 int (*fn)(struct mount_info *))
     954                 :            : {
     955                 :            :         int progress = 0;
     956                 :            : 
     957 [ #  # ][ #  # ]:          0 :         MNT_TREE_WALK(m, prev, MNT_WALK_NONE, fn, (struct list_head *) NULL, progress);
         [ #  # ][ #  # ]
     958                 :            : 
     959                 :            :         return 0;
     960                 :            : }
     961                 :            : 
     962                 :          6 : static char *resolve_source(struct mount_info *mi)
     963                 :            : {
     964         [ +  - ]:          6 :         if (kdev_major(mi->s_dev) == 0)
     965                 :            :                 /*
     966                 :            :                  * Anonymous block device. Kernel creates them for
     967                 :            :                  * diskless mounts.
     968                 :            :                  */
     969                 :          6 :                 return mi->source;
     970                 :            : 
     971                 :          0 :         pr_err("No device for %s mount\n", mi->mountpoint);
     972                 :          0 :         return NULL;
     973                 :            : }
     974                 :            : 
     975                 :         16 : static int restore_shared_options(struct mount_info *mi, bool private, bool shared, bool slave)
     976                 :            : {
     977                 :          8 :         pr_debug("%d:%s private %d shared %d slave %d\n",
     978                 :            :                         mi->mnt_id, mi->mountpoint, private, shared, slave);
     979                 :            : 
     980 [ +  + ][ -  + ]:          8 :         if (private && mount(NULL, mi->mountpoint, NULL, MS_PRIVATE, NULL)) {
     981                 :          0 :                 pr_perror("Unable to make %s private", mi->mountpoint);
     982                 :            :                 return -1;
     983                 :            :         }
     984 [ -  + ][ #  # ]:          8 :         if (slave && mount(NULL, mi->mountpoint, NULL, MS_SLAVE, NULL)) {
     985                 :          0 :                 pr_perror("Unable to make %s slave", mi->mountpoint);
     986                 :            :                 return -1;
     987                 :            :         }
     988 [ -  + ][ #  # ]:          8 :         if (shared && mount(NULL, mi->mountpoint, NULL, MS_SHARED, NULL)) {
     989                 :          0 :                 pr_perror("Unable to make %s shared", mi->mountpoint);
     990                 :            :                 return -1;
     991                 :            :         }
     992                 :            : 
     993                 :            :         return 0;
     994                 :            : }
     995                 :            : 
     996                 :            : /*
     997                 :            :  * Umount points, which are propagated in slave parents, because
     998                 :            :  * we can't be sure, that they were inherited in a real life.
     999                 :            :  */
    1000                 :          8 : static int umount_from_slaves(struct mount_info *mi)
    1001                 :            : {
    1002                 :            :         struct mount_info *t;
    1003                 :            :         char mpath[PATH_MAX];
    1004                 :            : 
    1005         [ -  + ]:          4 :         list_for_each_entry(t, &mi->parent->mnt_slave_list, mnt_slave) {
    1006         [ #  # ]:          0 :                 if (!t->mounted)
    1007                 :          0 :                         continue;
    1008                 :            : 
    1009                 :          0 :                 snprintf(mpath, sizeof(mpath), "%s/%s",
    1010                 :          0 :                                 t->mountpoint, basename(mi->mountpoint));
    1011                 :          0 :                 pr_debug("\t\tUmount %s\n", mpath);
    1012         [ #  # ]:          0 :                 if (umount(mpath) == -1) {
    1013                 :          0 :                         pr_perror("Can't umount %s", mpath);
    1014                 :            :                         return -1;
    1015                 :            :                 }
    1016                 :            :         }
    1017                 :            : 
    1018                 :            :         return 0;
    1019                 :            : }
    1020                 :            : 
    1021                 :            : /*
    1022                 :            :  * If something is mounted in one shared point, it will be spread in
    1023                 :            :  * all other points from this shared group.
    1024                 :            :  *
    1025                 :            :  * Look at Documentation/filesystems/sharedsubtree.txt for more details
    1026                 :            :  */
    1027                 :          6 : static int propagate_siblings(struct mount_info *mi)
    1028                 :            : {
    1029                 :            :         struct mount_info *t;
    1030                 :            : 
    1031                 :            :         /*
    1032                 :            :          * Find all mounts, which must be bind-mounted from this one
    1033                 :            :          * to inherite shared group or master id
    1034                 :            :          */
    1035         [ -  + ]:          6 :         list_for_each_entry(t, &mi->mnt_share, mnt_share) {
    1036                 :          0 :                 pr_debug("\t\tBind %s\n", t->mountpoint);
    1037                 :          0 :                 t->bind = mi;
    1038                 :            :         }
    1039                 :            : 
    1040         [ -  + ]:          6 :         list_for_each_entry(t, &mi->mnt_slave_list, mnt_slave) {
    1041                 :          0 :                 pr_debug("\t\tBind %s\n", t->mountpoint);
    1042                 :          0 :                 t->bind = mi;
    1043                 :            :         }
    1044                 :            : 
    1045                 :          6 :         return 0;
    1046                 :            : }
    1047                 :            : 
    1048                 :          6 : static int propagate_mount(struct mount_info *mi)
    1049                 :            : {
    1050                 :            :         struct mount_info *t;
    1051                 :            : 
    1052                 :          6 :         propagate_siblings(mi);
    1053                 :            : 
    1054         [ +  + ]:          6 :         if (!mi->parent)
    1055                 :            :                 goto skip_parent;
    1056                 :            : 
    1057                 :          4 :         umount_from_slaves(mi);
    1058                 :            : 
    1059                 :            :         /* Propagate this mount to everyone from a parent group */
    1060                 :            : 
    1061         [ -  + ]:          4 :         list_for_each_entry(t, &mi->parent->mnt_share, mnt_share) {
    1062                 :            :                 struct mount_info *c;
    1063                 :            : 
    1064         [ #  # ]:          0 :                 list_for_each_entry(c, &t->children, siblings) {
    1065         [ #  # ]:          0 :                         if (mounts_equal(mi, c, false)) {
    1066                 :          0 :                                 pr_debug("\t\tPropogate %s\n", c->mountpoint);
    1067                 :          0 :                                 c->mounted = true;
    1068                 :          0 :                                 propagate_siblings(c);
    1069                 :          0 :                                 umount_from_slaves(c);
    1070                 :            :                         }
    1071                 :            :                 }
    1072                 :            :         }
    1073                 :            : 
    1074                 :            : skip_parent:
    1075                 :            :         /*
    1076                 :            :          * FIXME Currently non-root mounts can be restored
    1077                 :            :          * only if a proper root mount exists
    1078                 :            :          */
    1079 [ +  + ][ +  - ]:          6 :         if (fsroot_mounted(mi) || mi->parent == NULL)
    1080         [ -  + ]:          6 :                 list_for_each_entry(t, &mi->mnt_bind, mnt_bind) {
    1081         [ #  # ]:          0 :                         if (t->bind)
    1082                 :          0 :                                 continue;
    1083         [ #  # ]:          0 :                         if (t->master_id)
    1084                 :          0 :                                 continue;
    1085                 :          0 :                         t->bind = mi;
    1086                 :            :                 }
    1087                 :            : 
    1088                 :          6 :         return 0;
    1089                 :            : }
    1090                 :            : 
    1091                 :          6 : static int do_new_mount(struct mount_info *mi)
    1092                 :            : {
    1093                 :            :         char *src;
    1094                 :          6 :         struct fstype *tp = mi->fstype;
    1095                 :            :         struct mount_info *t;
    1096                 :            : 
    1097                 :          6 :         src = resolve_source(mi);
    1098         [ +  - ]:          6 :         if (!src)
    1099                 :            :                 return -1;
    1100                 :            : 
    1101                 :            :         /*
    1102                 :            :          * Wait while all parent are not mounted
    1103                 :            :          *
    1104                 :            :          * FIXME a child is shared only between parents,
    1105                 :            :          * who was present in a moment of birth
    1106                 :            :          */
    1107         [ -  + ]:          6 :         if (mi->parent->flags & MS_SHARED) {
    1108         [ #  # ]:          0 :                 list_for_each_entry(t, &mi->parent->mnt_share, mnt_share) {
    1109         [ #  # ]:          0 :                         if (!t->mounted) {
    1110                 :          0 :                                 pr_debug("\t\tPostpone %s due to %s\n",
    1111                 :            :                                                 mi->mountpoint, t->mountpoint);
    1112                 :          0 :                                 return 1;
    1113                 :            :                         }
    1114                 :            :                 }
    1115                 :            :         }
    1116                 :            : 
    1117         [ -  + ]:          6 :         if (mount(src, mi->mountpoint, tp->name,
    1118                 :          6 :                         mi->flags & (~MS_SHARED), mi->options) < 0) {
    1119                 :          0 :                 pr_perror("Can't mount at %s", mi->mountpoint);
    1120                 :          0 :                 return -1;
    1121                 :            :         }
    1122                 :            : 
    1123         [ +  - ]:          6 :         if (restore_shared_options(mi, 0, mi->shared_id, 0))
    1124                 :            :                 return -1;
    1125                 :            : 
    1126                 :          6 :         mi->mounted = true;
    1127                 :            : 
    1128 [ +  + ][ +  - ]:          6 :         if (tp->restore && tp->restore(mi))
    1129                 :            :                 return -1;
    1130                 :            : 
    1131                 :            :         return 0;
    1132                 :            : }
    1133                 :            : 
    1134                 :          0 : static int restore_ext_mount(struct mount_info *mi)
    1135                 :            : {
    1136                 :            :         int ret;
    1137                 :            : 
    1138                 :          0 :         pr_debug("Restoring external bind mount %s\n", mi->mountpoint);
    1139                 :          0 :         ret = cr_plugin_restore_ext_mount(mi->mnt_id, mi->mountpoint, "/", NULL);
    1140         [ #  # ]:          0 :         if (ret)
    1141                 :          0 :                 pr_perror("Can't restore ext mount (%d)\n", ret);
    1142                 :          0 :         return ret;
    1143                 :            : }
    1144                 :            : 
    1145                 :          0 : static int do_bind_mount(struct mount_info *mi)
    1146                 :            : {
    1147 [ #  # ][ #  # ]:          0 :         bool shared = mi->shared_id && mi->shared_id == mi->bind->shared_id;
    1148                 :            : 
    1149         [ #  # ]:          0 :         if (!mi->need_plugin) {
    1150                 :            :                 char rpath[PATH_MAX];
    1151                 :            :                 int tok = 0;
    1152                 :            : 
    1153                 :            :                 /*
    1154                 :            :                  * Cut common part of root.
    1155                 :            :                  * For non-root binds the source is always "/" (checked)
    1156                 :            :                  * so this will result in this slash removal only.
    1157                 :            :                  */
    1158         [ #  # ]:          0 :                 while (mi->root[tok] == mi->bind->root[tok]) {
    1159                 :          0 :                         tok++;
    1160         [ #  # ]:          0 :                         if (mi->bind->root[tok] == '\0')
    1161                 :            :                                 break;
    1162         [ #  # ]:          0 :                         BUG_ON(mi->root[tok] == '\0');
    1163                 :            :                 }
    1164                 :            : 
    1165                 :          0 :                 snprintf(rpath, sizeof(rpath), "%s/%s",
    1166                 :            :                                 mi->bind->mountpoint, mi->root + tok);
    1167                 :          0 :                 pr_info("\tBind %s to %s\n", rpath, mi->mountpoint);
    1168                 :            : 
    1169         [ #  # ]:          0 :                 if (mount(rpath, mi->mountpoint, NULL,
    1170                 :            :                                         MS_BIND, NULL) < 0) {
    1171                 :          0 :                         pr_perror("Can't mount at %s", mi->mountpoint);
    1172                 :          0 :                         return -1;
    1173                 :            :                 }
    1174                 :            :         } else {
    1175         [ #  # ]:          0 :                 if (restore_ext_mount(mi))
    1176                 :            :                         return -1;
    1177                 :            :         }
    1178                 :            : 
    1179                 :            :         /*
    1180                 :            :          * shared - the mount is in the same shared group with mi->bind
    1181                 :            :          * mi->shared_id && !shared - create a new shared group
    1182                 :            :          */
    1183 [ #  # ][ #  # ]:          0 :         if (restore_shared_options(mi, !shared && !mi->master_id,
                 [ #  # ]
    1184 [ #  # ][ #  # ]:          0 :                                         mi->shared_id && !shared,
    1185                 :          0 :                                         mi->master_id))
    1186                 :            :                 return -1;
    1187                 :            : 
    1188                 :          0 :         mi->mounted = true;
    1189                 :            : 
    1190                 :          0 :         return 0;
    1191                 :            : }
    1192                 :            : 
    1193                 :          8 : static bool can_mount_now(struct mount_info *mi)
    1194                 :            : {
    1195                 :            :         /* The root mount */
    1196         [ +  + ]:          8 :         if (!mi->parent)
    1197                 :            :                 return true;
    1198                 :            : 
    1199                 :            :         /*
    1200                 :            :          * Private root mounts can be mounted at any time
    1201                 :            :          */
    1202 [ +  - ][ -  + ]:         12 :         if (!mi->master_id && fsroot_mounted(mi))
    1203                 :            :                 return true;
    1204                 :            : 
    1205                 :            :         /*
    1206                 :            :          * Other mounts can be mounted only if they have
    1207                 :            :          * the master mount (see propagate_mount) or if we
    1208                 :            :          * expect a plugin to help us.
    1209                 :            :          */
    1210 [ #  # ][ #  # ]:          0 :         if (mi->bind || mi->need_plugin)
    1211                 :            :                 return true;
    1212                 :            : 
    1213                 :          0 :         return false;
    1214                 :            : }
    1215                 :            : 
    1216                 :          2 : static int do_mount_root(struct mount_info *mi)
    1217                 :            : {
    1218 [ +  - ][ -  + ]:          2 :         if (restore_shared_options(mi, !mi->shared_id && !mi->master_id,
                 [ +  - ]
    1219                 :          4 :                                                 mi->shared_id, mi->master_id))
    1220                 :            :                 return -1;
    1221                 :            : 
    1222                 :          2 :         mi->mounted = true;
    1223                 :            : 
    1224                 :          2 :         return 0;
    1225                 :            : }
    1226                 :            : 
    1227                 :          8 : static int do_mount_one(struct mount_info *mi)
    1228                 :            : {
    1229                 :            :         int ret;
    1230                 :            : 
    1231         [ +  - ]:          8 :         if (mi->mounted)
    1232                 :            :                 return 0;
    1233                 :            : 
    1234         [ -  + ]:          8 :         if (!can_mount_now(mi)) {
    1235                 :          0 :                 pr_debug("Postpone slave %s\n", mi->mountpoint);
    1236                 :          0 :                 return 1;
    1237                 :            :         }
    1238                 :            : 
    1239                 :          8 :         pr_debug("\tMounting %s @%s (%d)\n", mi->fstype->name, mi->mountpoint, mi->need_plugin);
    1240                 :            : 
    1241         [ +  + ]:          8 :         if (!mi->parent)
    1242                 :          2 :                 ret = do_mount_root(mi);
    1243 [ +  - ][ +  - ]:          6 :         else if (!mi->bind && !mi->need_plugin)
    1244                 :          6 :                 ret = do_new_mount(mi);
    1245                 :            :         else
    1246                 :          0 :                 ret = do_bind_mount(mi);
    1247                 :            : 
    1248 [ +  - ][ +  - ]:          6 :         if (ret == 0 && propagate_mount(mi))
    1249                 :            :                 return -1;
    1250                 :            : 
    1251         [ +  + ]:          6 :         if (mi->fstype->code == FSTYPE__UNSUPPORTED) {
    1252                 :            :                 struct statfs st;
    1253                 :            : 
    1254         [ -  + ]:          2 :                 if (statfs(mi->mountpoint, &st)) {
    1255                 :          0 :                         pr_perror("Unable to statfs %s", mi->mountpoint);
    1256                 :          0 :                         return -1;
    1257                 :            :                 }
    1258         [ -  + ]:          2 :                 if (st.f_type == BTRFS_SUPER_MAGIC)
    1259                 :          2 :                         mi->fstype = find_fstype_by_name("btrfs");
    1260                 :            :         }
    1261                 :            : 
    1262                 :          6 :         return ret;
    1263                 :            : }
    1264                 :            : 
    1265                 :          0 : static int do_umount_one(struct mount_info *mi)
    1266                 :            : {
    1267         [ #  # ]:          0 :         if (!mi->parent)
    1268                 :            :                 return 0;
    1269                 :            : 
    1270         [ #  # ]:          0 :         if (mount("none", mi->parent->mountpoint, "none", MS_REC|MS_PRIVATE, NULL)) {
    1271                 :          0 :                 pr_perror("Can't mark %s as private", mi->parent->mountpoint);
    1272                 :          0 :                 return -1;
    1273                 :            :         }
    1274                 :            : 
    1275         [ #  # ]:          0 :         if (umount(mi->mountpoint)) {
    1276                 :          0 :                 pr_perror("Can't umount at %s", mi->mountpoint);
    1277                 :          0 :                 return -1;
    1278                 :            :         }
    1279                 :            : 
    1280                 :          0 :         pr_info("Umounted at %s\n", mi->mountpoint);
    1281                 :          0 :         return 0;
    1282                 :            : }
    1283                 :            : 
    1284                 :          0 : static int clean_mnt_ns(struct mount_info *mntinfo_tree)
    1285                 :            : {
    1286                 :          0 :         pr_info("Cleaning mount namespace\n");
    1287                 :            : 
    1288                 :            :         /*
    1289                 :            :          * Mountinfos were collected at prepare stage
    1290                 :            :          */
    1291                 :            : 
    1292                 :          0 :         return mnt_tree_for_each_reverse(mntinfo_tree, do_umount_one);
    1293                 :            : }
    1294                 :            : 
    1295                 :          0 : static int cr_pivot_root(char *root)
    1296                 :            : {
    1297                 :          0 :         char put_root[] = "crtools-put-root.XXXXXX";
    1298                 :            : 
    1299         [ #  # ]:          0 :         pr_info("Move the root to %s\n", root ? : ".");
    1300                 :            : 
    1301         [ #  # ]:          0 :         if (root) {
    1302         [ #  # ]:          0 :                 if (chdir(root)) {
    1303                 :          0 :                         pr_perror("chdir(%s) failed", root);
    1304                 :          0 :                         return -1;
    1305                 :            :                 }
    1306                 :            :         }
    1307                 :            : 
    1308         [ #  # ]:          0 :         if (mkdtemp(put_root) == NULL) {
    1309                 :          0 :                 pr_perror("Can't create a temporary directory");
    1310                 :          0 :                 return -1;
    1311                 :            :         }
    1312                 :            : 
    1313         [ #  # ]:          0 :         if (pivot_root(".", put_root)) {
    1314                 :          0 :                 pr_perror("pivot_root(., %s) failed", put_root);
    1315         [ #  # ]:          0 :                 if (rmdir(put_root))
    1316                 :          0 :                         pr_perror("Can't remove the directory %s", put_root);
    1317                 :            :                 return -1;
    1318                 :            :         }
    1319                 :            : 
    1320         [ #  # ]:          0 :         if (mount("none", put_root, "none", MS_REC|MS_PRIVATE, NULL)) {
    1321                 :          0 :                 pr_perror("Can't remount root with MS_PRIVATE");
    1322                 :          0 :                 return -1;
    1323                 :            :         }
    1324                 :            : 
    1325         [ #  # ]:          0 :         if (mount("none", put_root, "none", MS_REC|MS_PRIVATE, NULL)) {
    1326                 :          0 :                 pr_perror("Can't remount root with MS_PRIVATE");
    1327                 :          0 :                 return -1;
    1328                 :            :         }
    1329                 :            : 
    1330         [ #  # ]:          0 :         if (umount2(put_root, MNT_DETACH)) {
    1331                 :          0 :                 pr_perror("Can't umount %s", put_root);
    1332                 :          0 :                 return -1;
    1333                 :            :         }
    1334         [ #  # ]:          0 :         if (rmdir(put_root)) {
    1335                 :          0 :                 pr_perror("Can't remove the directory %s", put_root);
    1336                 :          0 :                 return -1;
    1337                 :            :         }
    1338                 :            : 
    1339                 :            :         return 0;
    1340                 :            : }
    1341                 :            : 
    1342                 :      73012 : struct mount_info *mnt_entry_alloc()
    1343                 :            : {
    1344                 :            :         struct mount_info *new;
    1345                 :            : 
    1346         [ -  + ]:      73012 :         new = xzalloc(sizeof(struct mount_info));
    1347         [ +  - ]:      73012 :         if (new) {
    1348                 :      73012 :                 INIT_LIST_HEAD(&new->children);
    1349                 :      73012 :                 INIT_LIST_HEAD(&new->siblings);
    1350                 :      73012 :                 INIT_LIST_HEAD(&new->mnt_slave_list);
    1351                 :      73012 :                 INIT_LIST_HEAD(&new->mnt_share);
    1352                 :      73012 :                 INIT_LIST_HEAD(&new->mnt_bind);
    1353                 :      73012 :                 INIT_LIST_HEAD(&new->postpone);
    1354                 :            :         }
    1355                 :      73012 :         return new;
    1356                 :            : }
    1357                 :            : 
    1358                 :         64 : void mnt_entry_free(struct mount_info *mi)
    1359                 :            : {
    1360         [ +  - ]:         64 :         if (mi == NULL)
    1361                 :         64 :                 return;
    1362                 :            : 
    1363         [ +  - ]:         64 :         xfree(mi->root);
    1364         [ +  - ]:         64 :         xfree(mi->mountpoint);
    1365         [ +  - ]:         64 :         xfree(mi->source);
    1366         [ +  - ]:         64 :         xfree(mi->options);
    1367         [ +  - ]:         64 :         xfree(mi);
    1368                 :            : }
    1369                 :            : 
    1370                 :            : static void free_mntinfo(struct mount_info *pms)
    1371                 :            : {
    1372         [ +  + ]:         66 :         while (pms) {
    1373                 :            :                 struct mount_info *pm;
    1374                 :            : 
    1375                 :         64 :                 pm = pms->next;
    1376                 :         64 :                 mnt_entry_free(pms);
    1377                 :            :                 pms = pm;
    1378                 :            :         }
    1379                 :            : }
    1380                 :            : 
    1381                 :            : /*
    1382                 :            :  * mnt_roots is a temporary directory for restoring sub-trees of
    1383                 :            :  * non-root namespaces.
    1384                 :            :  */
    1385                 :            : static char *mnt_roots;
    1386                 :            : 
    1387                 :          0 : static int create_mnt_roots()
    1388                 :            : {
    1389         [ #  # ]:          0 :         if (mnt_roots)
    1390                 :            :                 return 0;
    1391                 :            : 
    1392 [ #  # ][ #  # ]:          0 :         if (chdir(opts.root ? : "/")) {
    1393                 :          0 :                 pr_perror("Unable to change working directory on %s", opts.root);
    1394                 :          0 :                 return -1;
    1395                 :            :         }
    1396                 :            : 
    1397         [ #  # ]:          0 :         mnt_roots = strdup(".criu.mntns.XXXXXX");
    1398         [ #  # ]:          0 :         if (mnt_roots == NULL) {
    1399                 :          0 :                 pr_perror("Can't allocate memory");
    1400                 :          0 :                 return -1;
    1401                 :            :         }
    1402                 :            : 
    1403         [ #  # ]:          0 :         if (mkdtemp(mnt_roots) == NULL) {
    1404                 :          0 :                 pr_perror("Unable to create a temporary directory");
    1405                 :          0 :                 mnt_roots = NULL;
    1406                 :          0 :                 return -1;
    1407                 :            :         }
    1408                 :            : 
    1409                 :            :         return 0;
    1410                 :            : }
    1411                 :            : 
    1412                 :        354 : int rst_collect_local_mntns()
    1413                 :            : {
    1414                 :            :         struct ns_id *nsid;
    1415                 :            : 
    1416                 :        354 :         nsid = shmalloc(sizeof(struct ns_id));
    1417         [ +  - ]:        354 :         if (nsid == NULL)
    1418                 :            :                 return -1;
    1419                 :            : 
    1420                 :        354 :         nsid->nd = &mnt_ns_desc;
    1421                 :        354 :         nsid->id = 0;
    1422                 :        354 :         nsid->pid = getpid();
    1423                 :            :         futex_set(&nsid->created, 1);
    1424                 :            : 
    1425                 :        354 :         mntinfo = collect_mntinfo(nsid);
    1426         [ +  - ]:        354 :         if (mntinfo == NULL)
    1427                 :            :                 return -1;
    1428                 :            : 
    1429                 :        354 :         nsid->next = ns_ids;
    1430                 :        354 :         ns_ids = nsid;
    1431                 :            : 
    1432                 :        354 :         pr_info("Add namespace %d pid %d\n", nsid->id, nsid->pid);
    1433                 :            : 
    1434                 :        354 :         return 0;
    1435                 :            : }
    1436                 :            : 
    1437                 :          2 : static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
    1438                 :            : {
    1439                 :          2 :         MntEntry *me = NULL;
    1440                 :            :         int img, ret;
    1441                 :            : 
    1442                 :          2 :         img = open_image(CR_FD_MNTS, O_RSTR, nsid->id);
    1443         [ +  - ]:          2 :         if (img < 0)
    1444                 :            :                 return -1;
    1445                 :            : 
    1446                 :          2 :         pr_debug("Reading mountpoint images\n");
    1447                 :            : 
    1448                 :            :         while (1) {
    1449                 :            :                 struct mount_info *pm;
    1450                 :         12 :                 char root[PATH_MAX] = ".";
    1451                 :            :                 int len, root_len = 1;
    1452                 :            : 
    1453                 :         12 :                 ret = pb_read_one_eof(img, &me, PB_MNT);
    1454         [ +  + ]:         12 :                 if (ret <= 0)
    1455                 :            :                         break;
    1456                 :            : 
    1457                 :         10 :                 pm = mnt_entry_alloc();
    1458         [ +  - ]:         10 :                 if (!pm)
    1459                 :            :                         goto err;
    1460                 :            : 
    1461                 :         10 :                 pm->nsid = nsid;
    1462                 :         10 :                 pm->next = *pms;
    1463                 :         10 :                 *pms = pm;
    1464                 :            : 
    1465                 :         10 :                 pm->mnt_id           = me->mnt_id;
    1466                 :         10 :                 pm->parent_mnt_id    = me->parent_mnt_id;
    1467                 :         10 :                 pm->s_dev            = me->root_dev;
    1468                 :         10 :                 pm->flags            = me->flags;
    1469                 :         10 :                 pm->shared_id                = me->shared_id;
    1470                 :         10 :                 pm->master_id                = me->master_id;
    1471                 :         10 :                 pm->need_plugin              = me->with_plugin;
    1472                 :         20 :                 pm->is_ns_root               = is_root(me->mountpoint);
    1473                 :            : 
    1474                 :            :                 /* FIXME: abort unsupported early */
    1475                 :         20 :                 pm->fstype           = decode_fstype(me->fstype);
    1476                 :            : 
    1477                 :         10 :                 pr_debug("\t\tGetting root for %d\n", pm->mnt_id);
    1478         [ -  + ]:         10 :                 pm->root = xstrdup(me->root);
    1479         [ +  - ]:         10 :                 if (!pm->root)
    1480                 :            :                         goto err;
    1481                 :            : 
    1482         [ -  + ]:         10 :                 if (nsid->id != root_item->ids->mnt_ns_id)
    1483                 :          0 :                         root_len = snprintf(root, sizeof(root), "%s/%d/",
    1484                 :            :                                                 mnt_roots, nsid->id);
    1485                 :         10 :                 len  = strlen(me->mountpoint) + root_len + 1;
    1486         [ -  + ]:         10 :                 pm->mountpoint = xmalloc(len);
    1487         [ +  - ]:         10 :                 if (!pm->mountpoint)
    1488                 :            :                         goto err;
    1489                 :            :                 /*
    1490                 :            :                  * For bind-mounts we would also fix the root here
    1491                 :            :                  * too, but bind-mounts restore merges mountpoint
    1492                 :            :                  * and root paths together, so there's no need in
    1493                 :            :                  * that.
    1494                 :            :                  */
    1495                 :            : 
    1496                 :            :                 strcpy(pm->mountpoint, root);
    1497                 :         10 :                 strcpy(pm->mountpoint + root_len, me->mountpoint);
    1498                 :            : 
    1499                 :         10 :                 pr_debug("\t\tGetting mpt for %d %s\n", pm->mnt_id, pm->mountpoint);
    1500                 :            : 
    1501                 :         10 :                 pr_debug("\t\tGetting source for %d\n", pm->mnt_id);
    1502         [ -  + ]:         10 :                 pm->source = xstrdup(me->source);
    1503         [ +  - ]:         10 :                 if (!pm->source)
    1504                 :            :                         goto err;
    1505                 :            : 
    1506                 :         10 :                 pr_debug("\t\tGetting opts for %d\n", pm->mnt_id);
    1507         [ -  + ]:         10 :                 pm->options = xstrdup(me->options);
    1508         [ +  - ]:         10 :                 if (!pm->options)
    1509                 :            :                         goto err;
    1510                 :            : 
    1511                 :         10 :                 pr_debug("\tRead %d mp @ %s\n", pm->mnt_id, pm->mountpoint);
    1512                 :         10 :         }
    1513                 :            : 
    1514         [ -  + ]:          2 :         if (me)
    1515                 :          0 :                 mnt_entry__free_unpacked(me, NULL);
    1516                 :            : 
    1517                 :          2 :         close(img);
    1518                 :            : 
    1519                 :          2 :         return 0;
    1520                 :            : err:
    1521                 :          0 :         close_safe(&img);
    1522                 :          0 :         return -1;
    1523                 :            : }
    1524                 :            : 
    1525                 :          2 : static struct mount_info *read_mnt_ns_img()
    1526                 :            : {
    1527                 :          2 :         struct mount_info *pms = NULL;
    1528                 :            :         struct ns_id *nsid;
    1529                 :            : 
    1530                 :          2 :         nsid = ns_ids;
    1531         [ +  + ]:          4 :         while (nsid) {
    1532         [ -  + ]:          2 :                 if (nsid->nd != &mnt_ns_desc) {
    1533                 :          0 :                         nsid = nsid->next;
    1534                 :          0 :                         continue;
    1535                 :            :                 }
    1536                 :            : 
    1537         [ -  + ]:          2 :                 if (nsid->id != root_item->ids->mnt_ns_id)
    1538         [ #  # ]:          0 :                         if (create_mnt_roots(true))
    1539                 :            :                                 return NULL;
    1540                 :            : 
    1541         [ +  - ]:          2 :                 if (collect_mnt_from_image(&pms, nsid))
    1542                 :            :                         goto err;
    1543                 :            : 
    1544                 :          2 :                 nsid = nsid->next;
    1545                 :            :         }
    1546                 :            : 
    1547                 :            :         /* Here is not matter where the mount list is saved */
    1548                 :          2 :         mntinfo = pms;
    1549                 :            : 
    1550                 :          2 :         return pms;
    1551                 :            : err:
    1552                 :            :         return NULL;
    1553                 :            : }
    1554                 :            : 
    1555                 :         18 : char *rst_get_mnt_root(int mnt_id)
    1556                 :            : {
    1557                 :            :         struct mount_info *m;
    1558                 :            :         static char path[PATH_MAX] = "/";
    1559                 :            : 
    1560         [ -  + ]:         18 :         if (!(root_ns_mask & CLONE_NEWNS))
    1561                 :            :                 return path;
    1562                 :            : 
    1563         [ #  # ]:          0 :         if (mnt_id == -1)
    1564                 :            :                 return path;
    1565                 :            : 
    1566                 :            :         m = lookup_mnt_id(mnt_id);
    1567         [ #  # ]:          0 :         if (m == NULL)
    1568                 :            :                 return NULL;
    1569                 :            : 
    1570         [ #  # ]:          0 :         if (m->nsid->pid == getpid())
    1571                 :            :                 return path;
    1572                 :            : 
    1573                 :          0 :         snprintf(path, sizeof(path), "%s/%d/",
    1574                 :          0 :                         mnt_roots, m->nsid->id);
    1575                 :            : 
    1576                 :          0 :         return path;
    1577                 :            : }
    1578                 :            : 
    1579                 :        347 : int restore_task_mnt_ns(struct ns_id *nsid, pid_t pid)
    1580                 :            : {
    1581                 :            :         char path[PATH_MAX];
    1582                 :            : 
    1583         [ -  + ]:        347 :         if (root_item->ids->mnt_ns_id == nsid->id)
    1584                 :            :                 return 0;
    1585                 :            : 
    1586         [ #  # ]:          0 :         if (nsid->pid != getpid()) {
    1587                 :            :                 int fd;
    1588                 :            : 
    1589                 :          0 :                 futex_wait_while_eq(&nsid->created, 0);
    1590         [ #  # ]:          0 :                 fd = open_proc(nsid->pid, "ns/mnt");
    1591         [ #  # ]:          0 :                 if (fd < 0)
    1592                 :            :                         return -1;
    1593                 :            : 
    1594         [ #  # ]:          0 :                 if (setns(fd, CLONE_NEWNS)) {
    1595                 :          0 :                         pr_perror("Unable to change mount namespace");
    1596                 :          0 :                         return -1;
    1597                 :            :                 }
    1598                 :            :                 return 0;
    1599                 :            :         }
    1600                 :            : 
    1601         [ #  # ]:          0 :         if (unshare(CLONE_NEWNS)) {
    1602                 :          0 :                 pr_perror("Unable to unshare mount namespace");
    1603                 :          0 :                 return -1;
    1604                 :            :         }
    1605                 :            : 
    1606                 :          0 :         snprintf(path, sizeof(path), "%s/%d/", mnt_roots, nsid->id);
    1607                 :            : 
    1608         [ #  # ]:          0 :         if (cr_pivot_root(path))
    1609                 :            :                 return -1;
    1610                 :            : 
    1611                 :          0 :         futex_set_and_wake(&nsid->created, 1);
    1612                 :            : 
    1613                 :          0 :         return 0;
    1614                 :            : }
    1615                 :            : 
    1616                 :            : /*
    1617                 :            :  * All nested mount namespaces are restore as sub-trees of the root namespace.
    1618                 :            :  */
    1619                 :          2 : static int prepare_roots_yard(void)
    1620                 :            : {
    1621                 :            :         char path[PATH_MAX];
    1622                 :            :         struct ns_id *nsid;
    1623                 :            : 
    1624         [ -  + ]:          2 :         if (mnt_roots == NULL)
    1625                 :            :                 return 0;
    1626                 :            : 
    1627         [ #  # ]:          0 :         if (mount("none", mnt_roots, "tmpfs", 0, NULL)) {
    1628                 :          0 :                 pr_perror("Unable to mount tmpfs in %s", mnt_roots);
    1629                 :          0 :                 return -1;
    1630                 :            :         }
    1631         [ #  # ]:          0 :         if (mount("none", mnt_roots, NULL, MS_PRIVATE, NULL))
    1632                 :            :                 return -1;
    1633                 :            : 
    1634                 :          0 :         nsid = ns_ids;
    1635         [ #  # ]:          0 :         while (nsid) {
    1636         [ #  # ]:          0 :                 if (nsid->nd != &mnt_ns_desc) {
    1637                 :          0 :                         nsid = nsid->next;
    1638                 :          0 :                         continue;
    1639                 :            :                 }
    1640                 :            : 
    1641                 :          0 :                 snprintf(path, sizeof(path), "%s/%d",
    1642                 :            :                                 mnt_roots, nsid->id);
    1643                 :            : 
    1644         [ #  # ]:          0 :                 if (mkdir(path, 0600)) {
    1645                 :          0 :                         pr_perror("Unable to create %s", path);
    1646                 :          0 :                         return -1;
    1647                 :            :                 }
    1648                 :          0 :                 nsid = nsid->next;
    1649                 :            :         }
    1650                 :            : 
    1651                 :            :         return 0;
    1652                 :            : }
    1653                 :            : 
    1654                 :          4 : static int populate_mnt_ns(int ns_pid, struct mount_info *mis)
    1655                 :            : {
    1656                 :            :         struct mount_info *pms;
    1657                 :            :         struct ns_id *nsid;
    1658                 :            : 
    1659         [ +  - ]:          2 :         if (prepare_roots_yard())
    1660                 :            :                 return -1;
    1661                 :            : 
    1662                 :          2 :         pms = mnt_build_tree(mis);
    1663         [ +  - ]:          2 :         if (!pms)
    1664                 :            :                 return -1;
    1665                 :            : 
    1666         [ +  + ]:          4 :         for (nsid = ns_ids; nsid; nsid = nsid->next) {
    1667         [ -  + ]:          2 :                 if (nsid->nd != &mnt_ns_desc)
    1668                 :          0 :                         continue;
    1669                 :            : 
    1670                 :          2 :                 nsid->mnt.mntinfo_tree = pms;
    1671                 :            :         }
    1672                 :            : 
    1673         [ +  - ]:          2 :         if (validate_mounts(mis, false))
    1674                 :            :                 return -1;
    1675                 :            : 
    1676                 :          2 :         return mnt_tree_for_each(pms, do_mount_one);
    1677                 :            : }
    1678                 :            : 
    1679                 :        237 : int fini_mnt_ns()
    1680                 :            : {
    1681                 :            :         int ret = 0;
    1682                 :            : 
    1683         [ -  + ]:        237 :         if (mnt_roots == NULL)
    1684                 :            :                 return 0;
    1685                 :            : 
    1686         [ #  # ]:          0 :         if (mount("none", mnt_roots, "none", MS_REC|MS_PRIVATE, NULL)) {
    1687                 :          0 :                 pr_perror("Can't remount root with MS_PRIVATE");
    1688                 :            :                 ret = 1;
    1689                 :            :         }
    1690                 :            :         /*
    1691                 :            :          * Don't exit after a first error, becuase this function
    1692                 :            :          * can be used to rollback in a error case.
    1693                 :            :          * Don't worry about MNT_DETACH, because files are restored after this
    1694                 :            :          * and nobody will not be restored from a wrong mount namespace.
    1695                 :            :          */
    1696         [ #  # ]:          0 :         if (umount2(mnt_roots, MNT_DETACH)) {
    1697                 :          0 :                 pr_perror("Can't unmount %s", mnt_roots);
    1698                 :            :                 ret = 1;
    1699                 :            :         }
    1700         [ #  # ]:          0 :         if (rmdir(mnt_roots)) {
    1701                 :          0 :                 pr_perror("Can't remove the directory %s", mnt_roots);
    1702                 :            :                 ret = 1;
    1703                 :            :         }
    1704                 :            : 
    1705                 :          0 :         return ret;
    1706                 :            : }
    1707                 :            : 
    1708                 :          2 : int prepare_mnt_ns(int ns_pid)
    1709                 :            : {
    1710                 :            :         int ret = -1;
    1711                 :            :         struct mount_info *mis, *old;
    1712                 :          2 :         struct ns_id ns = { .pid = getpid(), .nd = &mnt_ns_desc };
    1713                 :            : 
    1714                 :          2 :         pr_info("Restoring mount namespace\n");
    1715                 :            : 
    1716                 :          2 :         old = collect_mntinfo(&ns);
    1717         [ +  - ]:          2 :         if (old == NULL)
    1718                 :            :                 return -1;
    1719                 :            : 
    1720                 :          2 :         close_proc();
    1721                 :            : 
    1722                 :          2 :         mis = read_mnt_ns_img(ns_pid);
    1723         [ +  - ]:          2 :         if (!mis)
    1724                 :            :                 goto out;
    1725                 :            : 
    1726 [ +  - ][ -  + ]:          2 :         if (chdir(opts.root ? : "/")) {
    1727         [ #  # ]:          0 :                 pr_perror("chdir(%s) failed", opts.root ? : "/");
    1728                 :          0 :                 return -1;
    1729                 :            :         }
    1730                 :            : 
    1731                 :            :         /*
    1732                 :            :          * The new mount namespace is filled with the mountpoint
    1733                 :            :          * clones from the original one. We have to umount them
    1734                 :            :          * prior to recreating new ones.
    1735                 :            :          */
    1736         [ -  + ]:          2 :         if (!opts.root) {
    1737         [ #  # ]:          0 :                 if (clean_mnt_ns(ns.mnt.mntinfo_tree))
    1738                 :            :                         return -1;
    1739                 :            :         } else {
    1740                 :            :                 struct mount_info *mi;
    1741                 :            : 
    1742                 :            :                 /* moving a mount residing under a shared mount is invalid. */
    1743                 :          2 :                 mi = mount_resolve_path(ns.mnt.mntinfo_tree, opts.root);
    1744         [ -  + ]:          2 :                 if (mi == NULL) {
    1745                 :          0 :                         pr_err("Unable to find mount point for %s\n", opts.root);
    1746                 :          0 :                         return -1;
    1747                 :            :                 }
    1748         [ -  + ]:          2 :                 if (mi->parent == NULL) {
    1749                 :          0 :                         pr_err("New root and old root are the same\n");
    1750                 :          0 :                         return -1;
    1751                 :            :                 }
    1752                 :            : 
    1753                 :            :                 /* Our root is mounted over the parent (in the same directory) */
    1754         [ -  + ]:          2 :                 if (!strcmp(mi->parent->mountpoint, mi->mountpoint)) {
    1755                 :          0 :                         pr_err("The parent of the new root is unreachable\n");
    1756                 :          0 :                         return -1;
    1757                 :            :                 }
    1758                 :            : 
    1759         [ +  - ]:          2 :                 if (mount("none", mi->parent->mountpoint + 1, "none", MS_SLAVE, NULL)) {
    1760                 :          0 :                         pr_perror("Can't remount the parent of the new root with MS_SLAVE");
    1761                 :          0 :                         return -1;
    1762                 :            :                 }
    1763                 :            :         }
    1764                 :            : 
    1765                 :            :         free_mntinfo(old);
    1766                 :            : 
    1767                 :          2 :         ret = populate_mnt_ns(ns_pid, mis);
    1768         [ #  # ]:          0 :         if (ret)
    1769                 :            :                 goto out;
    1770                 :            : 
    1771         [ #  # ]:          0 :         if (opts.root)
    1772                 :          0 :                 ret = cr_pivot_root(NULL);
    1773                 :            : out:
    1774                 :          0 :         return ret;
    1775                 :            : }
    1776                 :            : 
    1777                 :     147939 : int mntns_collect_root(pid_t pid)
    1778                 :            : {
    1779                 :            :         static int mntns_root_pid = -1;
    1780                 :            : 
    1781                 :            :         int fd, pfd;
    1782                 :            :         int ret;
    1783                 :            :         char path[PATH_MAX + 1];
    1784                 :            : 
    1785         [ +  + ]:     147939 :         if (mntns_root_pid == pid) /* The required root is already opened */
    1786                 :     145789 :                 return get_service_fd(ROOT_FD_OFF);
    1787                 :            : 
    1788                 :       2150 :         close_service_fd(ROOT_FD_OFF);
    1789                 :            : 
    1790         [ +  + ]:       2150 :         if (!(root_ns_mask & CLONE_NEWNS)) {
    1791                 :            :                 /*
    1792                 :            :                  * If criu and tasks we dump live in the same mount
    1793                 :            :                  * namespace, we can just open the root directory.
    1794                 :            :                  * All paths resolution would occur relative to criu's
    1795                 :            :                  * root. Even if it is not namespace's root, provided
    1796                 :            :                  * file paths are resolved, we'd get consistent dump.
    1797                 :            :                  */
    1798                 :            :                 fd = open("/", O_RDONLY | O_DIRECTORY);
    1799         [ -  + ]:       1308 :                 if (fd < 0) {
    1800                 :          0 :                         pr_perror("Can't open root\n");
    1801                 :          0 :                         return -1;
    1802                 :            :                 }
    1803                 :            : 
    1804                 :            :                 goto set_root;
    1805                 :            :         }
    1806                 :            : 
    1807                 :            :         /*
    1808                 :            :          * If /proc/pid/root links on '/', it signs that a root of the task
    1809                 :            :          * and a root of mntns is the same.
    1810                 :            :          */
    1811                 :            : 
    1812                 :        842 :         pfd = open_pid_proc(pid);
    1813                 :        842 :         ret = readlinkat(pfd, "root", path, sizeof(path) - 1);
    1814         [ -  + ]:        842 :         if (ret < 0) {
    1815                 :          0 :                 close_pid_proc();
    1816                 :          0 :                 return ret;
    1817                 :            :         }
    1818                 :            : 
    1819                 :        842 :         path[ret] = '\0';
    1820                 :            : 
    1821 [ +  - ][ -  + ]:        842 :         if (ret != 1 || path[0] != '/') {
    1822                 :          0 :                 pr_err("The root task has another root than mntns: %s\n", path);
    1823                 :          0 :                 close_pid_proc();
    1824                 :          0 :                 return -1;
    1825                 :            :         }
    1826                 :            : 
    1827                 :            :         fd = openat(pfd, "root", O_RDONLY | O_DIRECTORY, 0);
    1828                 :        842 :         close_pid_proc();
    1829         [ -  + ]:        842 :         if (fd < 0) {
    1830                 :          0 :                 pr_perror("Can't open the task root");
    1831                 :          0 :                 return -1;
    1832                 :            :         }
    1833                 :            : 
    1834                 :            : set_root:
    1835                 :       2150 :         ret = install_service_fd(ROOT_FD_OFF, fd);
    1836         [ +  - ]:       2150 :         if (ret >= 0)
    1837                 :       2150 :                 mntns_root_pid = pid;
    1838                 :       2150 :         close(fd);
    1839                 :       2150 :         return ret;
    1840                 :            : }
    1841                 :            : 
    1842                 :      10733 : struct ns_id *lookup_nsid_by_mnt_id(int mnt_id)
    1843                 :            : {
    1844                 :            :         struct mount_info *mi;
    1845                 :            : 
    1846                 :            :         /*
    1847                 :            :          * Kernel before 3.15 doesn't show mnt_id for file descriptors.
    1848                 :            :          * mnt_id isn't saved for files, if mntns isn't dumped.
    1849                 :            :          * In both these cases we have only one root, so here
    1850                 :            :          * is not matter which mount will be restured.
    1851                 :            :          */
    1852         [ +  - ]:      10733 :         if (mnt_id == -1)
    1853                 :      10733 :                 mi = mntinfo;
    1854                 :            :         else
    1855                 :            :                 mi = lookup_mnt_id(mnt_id);
    1856                 :            : 
    1857         [ +  - ]:      10733 :         if (mi == NULL)
    1858                 :            :                 return NULL;
    1859                 :            : 
    1860                 :      10733 :         return mi->nsid;
    1861                 :            : }
    1862                 :            : 
    1863                 :       1344 : int collect_mnt_namespaces(void)
    1864                 :            : {
    1865                 :            :         struct mount_info *pm, *pms;
    1866                 :            :         struct ns_id *ns;
    1867                 :            :         int ret = -1;
    1868                 :            : 
    1869         [ +  + ]:       3318 :         for (ns = ns_ids; ns; ns = ns->next) {
    1870         [ +  + ]:       1974 :                 if (ns->pid == getpid()) {
    1871         [ +  + ]:       1344 :                         if (!(root_ns_mask & CLONE_NEWNS)) {
    1872                 :        714 :                                 mntinfo = collect_mntinfo(ns);
    1873         [ +  - ]:        714 :                                 if (mntinfo == NULL)
    1874                 :            :                                         return -1;
    1875                 :            :                         }
    1876                 :            :                         /* Skip current namespaces, which are in the list too  */
    1877                 :       1344 :                         continue;
    1878                 :            :                 }
    1879                 :            : 
    1880         [ -  + ]:        630 :                 if (!(ns->nd->cflag & CLONE_NEWNS))
    1881                 :          0 :                         continue;
    1882                 :            : 
    1883                 :        630 :                 pr_info("Dump MNT namespace (mountpoints) %d via %d\n",
    1884                 :            :                                 ns->id, ns->pid);
    1885                 :        630 :                 pms = collect_mntinfo(ns);
    1886         [ +  - ]:        630 :                 if (pms == NULL)
    1887                 :            :                         goto err;
    1888                 :            : 
    1889         [ +  - ]:        630 :                 if (mntinfo == NULL)
    1890                 :        630 :                         mntinfo = pms;
    1891                 :            :                 else {
    1892         [ #  # ]:          0 :                         for (pm = mntinfo; pm->next != NULL; pm = pm->next);
    1893                 :            : 
    1894                 :          0 :                         pm->next = pms;
    1895                 :            :                 }
    1896                 :            :         }
    1897                 :            :         ret = 0;
    1898                 :            : err:
    1899                 :       1344 :         return ret;
    1900                 :            : }
    1901                 :            : 
    1902                 :        448 : int dump_mnt_namespaces(void)
    1903                 :            : {
    1904                 :            :         struct ns_id *ns;
    1905                 :            :         int ret = 0, n = 0;
    1906                 :            : 
    1907         [ +  + ]:       3754 :         for (ns = ns_ids; ns; ns = ns->next) {
    1908                 :            :                 /* Skip current namespaces, which are in the list too  */
    1909         [ +  + ]:       3306 :                 if (ns->pid == getpid()) {
    1910         [ +  + ]:       2240 :                         if (!(root_ns_mask & CLONE_NEWNS))
    1911                 :       1190 :                                 mntinfo = collect_mntinfo(ns);
    1912         [ +  - ]:       2240 :                                 if (mntinfo == NULL)
    1913                 :            :                                         return -1;
    1914                 :       2240 :                         continue;
    1915                 :            :                 }
    1916                 :            : 
    1917         [ +  + ]:       1066 :                 if (!(ns->nd->cflag & CLONE_NEWNS))
    1918                 :        856 :                         continue;
    1919                 :            : 
    1920                 :        210 :                 n++;
    1921                 :            : 
    1922 [ -  + ][ #  # ]:        210 :                 if (n == 2 && check_mnt_id()) {
    1923                 :          0 :                         pr_err("Nested mount namespaces are not supported "
    1924                 :            :                                 "without mnt_id in fdinfo\n");
    1925                 :          0 :                         return -1;
    1926                 :            :                 }
    1927                 :        210 :                 pr_info("Dump MNT namespace (mountpoints) %d via %d\n",
    1928                 :            :                                 ns->id, ns->pid);
    1929                 :        210 :                 ret = dump_mnt_ns(ns);
    1930         [ +  - ]:        210 :                 if (ret)
    1931                 :            :                         break;
    1932                 :            :         }
    1933                 :            : 
    1934                 :        448 :         return ret;
    1935                 :            : }
    1936                 :            : 
    1937                 :            : struct ns_desc mnt_ns_desc = NS_DESC_ENTRY(CLONE_NEWNS, "mnt");

Generated by: LCOV version 1.9