LCOV - code coverage report
Current view: top level - home/snorch/criu - files-reg.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 238 314 75.8 %
Date: 2014-04-22 Functions: 25 27 92.6 %
Branches: 104 210 49.5 %

           Branch data     Line data    Source code
       1                 :            : #include <stdlib.h>
       2                 :            : #include <unistd.h>
       3                 :            : #include <errno.h>
       4                 :            : #include <string.h>
       5                 :            : #include <sys/mman.h>
       6                 :            : #include <sys/types.h>
       7                 :            : #include <sys/stat.h>
       8                 :            : #include <sys/vfs.h>
       9                 :            : #include <ctype.h>
      10                 :            : 
      11                 :            : /* Stolen from kernel/fs/nfs/unlink.c */
      12                 :            : #define SILLYNAME_PREF ".nfs"
      13                 :            : #define SILLYNAME_SUFF_LEN (((unsigned)sizeof(u64) << 1) + ((unsigned)sizeof(unsigned int) << 1))
      14                 :            : 
      15                 :            : #include "cr_options.h"
      16                 :            : #include "fdset.h"
      17                 :            : #include "file-ids.h"
      18                 :            : #include "mount.h"
      19                 :            : #include "files.h"
      20                 :            : #include "image.h"
      21                 :            : #include "list.h"
      22                 :            : #include "util.h"
      23                 :            : #include "fs-magic.h"
      24                 :            : #include "asm/atomic.h"
      25                 :            : #include "namespaces.h"
      26                 :            : #include "proc_parse.h"
      27                 :            : 
      28                 :            : #include "protobuf.h"
      29                 :            : #include "protobuf/regfile.pb-c.h"
      30                 :            : #include "protobuf/remap-file-path.pb-c.h"
      31                 :            : 
      32                 :            : #include "files-reg.h"
      33                 :            : #include "plugin.h"
      34                 :            : 
      35                 :            : /*
      36                 :            :  * Ghost files are those not visible from the FS. Dumping them is
      37                 :            :  * nasty and the only way we have -- just carry its contents with
      38                 :            :  * us. Any brave soul to implement link unlinked file back?
      39                 :            :  */
      40                 :            : struct ghost_file {
      41                 :            :         struct list_head        list;
      42                 :            :         u32                     id;
      43                 :            : 
      44                 :            :         u32                     dev;
      45                 :            :         u32                     ino;
      46                 :            : 
      47                 :            :         struct file_remap       remap;
      48                 :            : };
      49                 :            : 
      50                 :            : static u32 ghost_file_ids = 1;
      51                 :            : static LIST_HEAD(ghost_files);
      52                 :            : 
      53                 :            : static mutex_t *ghost_file_mutex;
      54                 :            : 
      55                 :            : /*
      56                 :            :  * To rollback link remaps.
      57                 :            :  */
      58                 :            : struct link_remap_rlb {
      59                 :            :         struct list_head        list;
      60                 :            :         pid_t                   pid;
      61                 :            :         char                    *path;
      62                 :            : };
      63                 :            : static LIST_HEAD(link_remaps);
      64                 :            : 
      65                 :            : /*
      66                 :            :  * This constant is selected without any calculations. Just do not
      67                 :            :  * want to pick up too big files with us in the image.
      68                 :            :  */
      69                 :            : #define MAX_GHOST_FILE_SIZE     (1 * 1024 * 1024)
      70                 :            : 
      71                 :         24 : static int open_remap_ghost(struct reg_file_info *rfi,
      72                 :            :                 RemapFilePathEntry *rfe)
      73                 :            : {
      74                 :            :         struct ghost_file *gf;
      75                 :         24 :         GhostFileEntry *gfe = NULL;
      76                 :            :         int gfd, ifd, ghost_flags;
      77                 :            :         char *root, path[PATH_MAX];
      78                 :            : 
      79                 :         24 :         rfe->remap_id &= ~REMAP_GHOST;
      80         [ +  + ]:         24 :         list_for_each_entry(gf, &ghost_files, list)
      81         [ -  + ]:          6 :                 if (gf->id == rfe->remap_id)
      82                 :            :                         goto gf_found;
      83                 :            : 
      84                 :            :         /*
      85                 :            :          * Ghost not found. We will create one in the same dir
      86                 :            :          * as the very first client of it thus resolving any
      87                 :            :          * issues with cross-device links.
      88                 :            :          */
      89                 :            : 
      90                 :         18 :         pr_info("Opening ghost file %#x for %s\n", rfe->remap_id, rfi->path);
      91                 :            : 
      92                 :         18 :         root = rst_get_mnt_root(rfi->rfe->mnt_id);
      93         [ -  + ]:         18 :         if (root == NULL) {
      94                 :          0 :                 pr_err("The %d mount is not found\n", rfi->rfe->mnt_id);
      95                 :            :                 return -1;
      96                 :            :         }
      97                 :            : 
      98                 :         18 :         gf = shmalloc(sizeof(*gf));
      99         [ +  - ]:         18 :         if (!gf)
     100                 :            :                 return -1;
     101         [ -  + ]:         18 :         gf->remap.path = xmalloc(PATH_MAX);
     102         [ +  - ]:         18 :         if (!gf->remap.path)
     103                 :            :                 goto err;
     104                 :            : 
     105                 :         18 :         ifd = open_image(CR_FD_GHOST_FILE, O_RSTR, rfe->remap_id);
     106         [ +  - ]:         18 :         if (ifd < 0)
     107                 :            :                 goto err;
     108                 :            : 
     109         [ +  - ]:         18 :         if (pb_read_one(ifd, &gfe, PB_GHOST_FILE) < 0)
     110                 :            :                 goto close_ifd;
     111                 :            : 
     112                 :            :         /*
     113                 :            :          * For old formats where optional has_[dev|ino] is
     114                 :            :          * not present we will have zeros here which is quite
     115                 :            :          * a sign for "absent" fields.
     116                 :            :          */
     117                 :         18 :         gf->dev = gfe->dev;
     118                 :         18 :         gf->ino = gfe->ino;
     119                 :            : 
     120                 :         18 :         snprintf(gf->remap.path, PATH_MAX, "%s.cr.%x.ghost", rfi->path, rfe->remap_id);
     121                 :            : 
     122         [ +  + ]:         18 :         if (S_ISFIFO(gfe->mode)) {
     123         [ -  + ]:          2 :                 if (mknod(gf->remap.path, gfe->mode, 0)) {
     124                 :          0 :                         pr_perror("Can't create node for ghost file");
     125                 :            :                         goto close_ifd;
     126                 :            :                 }
     127                 :            :                 ghost_flags = O_RDWR; /* To not block */
     128                 :            :         } else
     129                 :            :                 ghost_flags = O_WRONLY | O_CREAT | O_EXCL;
     130                 :            : 
     131                 :         18 :         snprintf(path, sizeof(path), "%s/%s", root, gf->remap.path);
     132                 :         36 :         gfd = open(path, ghost_flags, gfe->mode);
     133         [ -  + ]:         18 :         if (gfd < 0) {
     134                 :          0 :                 pr_perror("Can't open ghost file %s", path);
     135                 :            :                 goto close_ifd;
     136                 :            :         }
     137                 :            : 
     138         [ -  + ]:         18 :         if (fchown(gfd, gfe->uid, gfe->gid) < 0) {
     139                 :          0 :                 pr_perror("Can't reset user/group on ghost %#x", rfe->remap_id);
     140                 :            :                 goto close_all;
     141                 :            :         }
     142                 :            : 
     143         [ +  + ]:         18 :         if (S_ISREG(gfe->mode)) {
     144         [ +  - ]:         16 :                 if (copy_file(ifd, gfd, 0) < 0)
     145                 :            :                         goto close_all;
     146                 :            :         }
     147                 :            : 
     148                 :         18 :         ghost_file_entry__free_unpacked(gfe, NULL);
     149                 :         18 :         close(ifd);
     150                 :         18 :         close(gfd);
     151                 :            : 
     152                 :         18 :         gf->id = rfe->remap_id;
     153                 :         18 :         gf->remap.users = 0;
     154                 :         18 :         list_add_tail(&gf->list, &ghost_files);
     155                 :            : gf_found:
     156                 :         24 :         rfi->remap = &gf->remap;
     157                 :            :         return 0;
     158                 :            : 
     159                 :            : close_all:
     160                 :          0 :         close_safe(&gfd);
     161                 :            : close_ifd:
     162                 :          0 :         close_safe(&ifd);
     163                 :            : err:
     164         [ #  # ]:          0 :         if (gfe)
     165                 :          0 :                 ghost_file_entry__free_unpacked(gfe, NULL);
     166         [ #  # ]:          0 :         xfree(gf->remap.path);
     167                 :          0 :         shfree_last(gf);
     168                 :            :         return -1;
     169                 :            : }
     170                 :            : 
     171                 :          4 : static int open_remap_linked(struct reg_file_info *rfi,
     172                 :            :                 RemapFilePathEntry *rfe)
     173                 :            : {
     174                 :            :         struct file_remap *rm;
     175                 :            :         struct file_desc *rdesc;
     176                 :            :         struct reg_file_info *rrfi;
     177                 :            : 
     178                 :          2 :         rdesc = find_file_desc_raw(FD_TYPES__REG, rfe->remap_id);
     179         [ -  + ]:          2 :         if (!rdesc) {
     180                 :          0 :                 pr_err("Can't find target file %x\n", rfe->remap_id);
     181                 :            :                 return -1;
     182                 :            :         }
     183                 :            : 
     184         [ -  + ]:          2 :         rm = xmalloc(sizeof(*rm));
     185         [ +  - ]:          2 :         if (!rm)
     186                 :            :                 return -1;
     187                 :            : 
     188                 :            :         rrfi = container_of(rdesc, struct reg_file_info, d);
     189                 :          2 :         pr_info("Remapped %s -> %s\n", rfi->path, rrfi->path);
     190                 :            : 
     191                 :          2 :         rm->path = rrfi->path;
     192                 :          2 :         rm->users = 0;
     193                 :          2 :         rfi->remap = rm;
     194                 :            :         return 0;
     195                 :            : }
     196                 :            : 
     197                 :         26 : static int collect_one_remap(void *obj, ProtobufCMessage *msg)
     198                 :            : {
     199                 :            :         int ret = -1;
     200                 :            :         RemapFilePathEntry *rfe;
     201                 :            :         struct file_desc *fdesc;
     202                 :            :         struct reg_file_info *rfi;
     203                 :            : 
     204                 :            :         rfe = pb_msg(msg, RemapFilePathEntry);
     205                 :            : 
     206                 :         26 :         fdesc = find_file_desc_raw(FD_TYPES__REG, rfe->orig_id);
     207         [ -  + ]:         26 :         if (fdesc == NULL) {
     208                 :          0 :                 pr_err("Remap for non existing file %#x\n",
     209                 :            :                                 rfe->orig_id);
     210                 :          0 :                 goto out;
     211                 :            :         }
     212                 :            : 
     213                 :            :         rfi = container_of(fdesc, struct reg_file_info, d);
     214                 :         26 :         pr_info("Configuring remap %#x -> %#x\n", rfi->rfe->id, rfe->remap_id);
     215                 :            : 
     216         [ +  + ]:         26 :         if (rfe->remap_id & REMAP_GHOST)
     217                 :         24 :                 ret = open_remap_ghost(rfi, rfe);
     218                 :            :         else
     219                 :          2 :                 ret = open_remap_linked(rfi, rfe);
     220                 :            : out:
     221                 :         26 :         return ret;
     222                 :            : }
     223                 :            : 
     224                 :            : struct collect_image_info remap_cinfo = {
     225                 :            :         .fd_type = CR_FD_REMAP_FPATH,
     226                 :            :         .pb_type = PB_REMAP_FPATH,
     227                 :            :         .collect = collect_one_remap,
     228                 :            : };
     229                 :            : 
     230                 :         32 : static int dump_ghost_file(int _fd, u32 id, const struct stat *st, dev_t phys_dev)
     231                 :            : {
     232                 :            :         int img;
     233                 :         32 :         GhostFileEntry gfe = GHOST_FILE_ENTRY__INIT;
     234                 :            : 
     235                 :         32 :         pr_info("Dumping ghost file contents (id %#x)\n", id);
     236                 :            : 
     237                 :         32 :         img = open_image(CR_FD_GHOST_FILE, O_DUMP, id);
     238         [ +  - ]:         32 :         if (img < 0)
     239                 :            :                 return -1;
     240                 :            : 
     241                 :         32 :         gfe.uid = st->st_uid;
     242                 :         32 :         gfe.gid = st->st_gid;
     243                 :         32 :         gfe.mode = st->st_mode;
     244                 :            : 
     245                 :         32 :         gfe.has_dev = gfe.has_ino = true;
     246                 :         32 :         gfe.dev = phys_dev;
     247                 :         32 :         gfe.ino = st->st_ino;
     248                 :            : 
     249         [ +  - ]:         32 :         if (pb_write_one(img, &gfe, PB_GHOST_FILE))
     250                 :            :                 return -1;
     251                 :            : 
     252         [ +  + ]:         32 :         if (S_ISREG(st->st_mode)) {
     253                 :            :                 int fd, ret;
     254                 :            :                 char lpath[PSFDS];
     255                 :            : 
     256                 :            :                 /*
     257                 :            :                  * Reopen file locally since it may have no read
     258                 :            :                  * permissions when drained
     259                 :            :                  */
     260                 :            :                 sprintf(lpath, "/proc/self/fd/%d", _fd);
     261                 :            :                 fd = open(lpath, O_RDONLY);
     262         [ -  + ]:         28 :                 if (fd < 0) {
     263                 :          0 :                         pr_perror("Can't open ghost original file");
     264                 :          0 :                         return -1;
     265                 :            :                 }
     266                 :         28 :                 ret = copy_file(fd, img, st->st_size);
     267                 :         28 :                 close(fd);
     268         [ +  - ]:         28 :                 if (ret)
     269                 :            :                         return -1;
     270                 :            :         }
     271                 :            : 
     272                 :         32 :         close(img);
     273                 :         32 :         return 0;
     274                 :            : }
     275                 :            : 
     276                 :          2 : void remap_put(struct file_remap *remap)
     277                 :            : {
     278                 :          2 :         mutex_lock(ghost_file_mutex);
     279         [ -  + ]:          2 :         if (--remap->users == 0) {
     280                 :          0 :                 pr_info("Unlink the ghost %s\n", remap->path);
     281                 :          0 :                 unlink(remap->path);
     282                 :            :         }
     283                 :          2 :         mutex_unlock(ghost_file_mutex);
     284                 :          2 : }
     285                 :            : 
     286                 :          6 : struct file_remap *lookup_ghost_remap(u32 dev, u32 ino)
     287                 :            : {
     288                 :            :         struct ghost_file *gf;
     289                 :            : 
     290                 :          6 :         mutex_lock(ghost_file_mutex);
     291         [ +  + ]:          8 :         list_for_each_entry(gf, &ghost_files, list) {
     292 [ +  + ][ +  - ]:          4 :                 if (gf->ino == ino && (gf->dev == dev)) {
     293                 :          2 :                         gf->remap.users++;
     294                 :          2 :                         mutex_unlock(ghost_file_mutex);
     295                 :          2 :                         return &gf->remap;
     296                 :            :                 }
     297                 :            :         }
     298                 :          4 :         mutex_unlock(ghost_file_mutex);
     299                 :            : 
     300                 :          4 :         return NULL;
     301                 :            : }
     302                 :            : 
     303                 :         80 : static int dump_ghost_remap(char *path, const struct stat *st,
     304                 :            :                                 int lfd, u32 id, struct ns_id *nsid)
     305                 :            : {
     306                 :            :         struct ghost_file *gf;
     307                 :         40 :         RemapFilePathEntry rpe = REMAP_FILE_PATH_ENTRY__INIT;
     308                 :            :         dev_t phys_dev;
     309                 :            : 
     310                 :         40 :         pr_info("Dumping ghost file for fd %d id %#x\n", lfd, id);
     311                 :            : 
     312         [ -  + ]:         40 :         if (st->st_size > MAX_GHOST_FILE_SIZE) {
     313                 :          0 :                 pr_err("Can't dump ghost file %s of %"PRIu64" size\n",
     314                 :            :                                 path, st->st_size);
     315                 :            :                 return -1;
     316                 :            :         }
     317                 :            : 
     318                 :         40 :         phys_dev = phys_stat_resolve_dev(nsid->mnt.mntinfo_tree, st->st_dev, path);
     319         [ +  + ]:         40 :         list_for_each_entry(gf, &ghost_files, list)
     320 [ +  - ][ -  + ]:          8 :                 if ((gf->dev == phys_dev) && (gf->ino == st->st_ino))
     321                 :            :                         goto dump_entry;
     322                 :            : 
     323         [ -  + ]:         32 :         gf = xmalloc(sizeof(*gf));
     324         [ +  - ]:         32 :         if (gf == NULL)
     325                 :            :                 return -1;
     326                 :            : 
     327                 :         32 :         gf->dev = phys_dev;
     328                 :         32 :         gf->ino = st->st_ino;
     329                 :         32 :         gf->id = ghost_file_ids++;
     330                 :         32 :         list_add_tail(&gf->list, &ghost_files);
     331                 :            : 
     332         [ +  - ]:         32 :         if (dump_ghost_file(lfd, gf->id, st, phys_dev))
     333                 :            :                 return -1;
     334                 :            : 
     335                 :            : dump_entry:
     336         [ -  + ]:         40 :         BUG_ON(gf->id & REMAP_GHOST);
     337                 :            : 
     338                 :         40 :         rpe.orig_id = id;
     339                 :         40 :         rpe.remap_id = gf->id | REMAP_GHOST;
     340                 :            : 
     341                 :         40 :         return pb_write_one(fdset_fd(glob_fdset, CR_FD_REMAP_FPATH),
     342                 :            :                         &rpe, PB_REMAP_FPATH);
     343                 :            : }
     344                 :            : 
     345                 :        448 : static void __rollback_link_remaps(bool do_unlink)
     346                 :            : {
     347                 :            :         struct link_remap_rlb *rlb, *tmp;
     348                 :            :         int mntns_root;
     349                 :            : 
     350         [ +  + ]:        448 :         if (!opts.link_remap_ok)
     351                 :            :                 return;
     352                 :            : 
     353         [ +  + ]:         32 :         list_for_each_entry_safe(rlb, tmp, &link_remaps, list) {
     354                 :          4 :                 mntns_root = mntns_collect_root(rlb->pid);
     355         [ +  - ]:          4 :                 if (mntns_root < 0)
     356                 :            :                         return;
     357                 :            :                 list_del(&rlb->list);
     358         [ -  + ]:          4 :                 if (do_unlink)
     359                 :          0 :                         unlinkat(mntns_root, rlb->path, 0);
     360         [ +  - ]:          4 :                 xfree(rlb->path);
     361         [ +  - ]:          4 :                 xfree(rlb);
     362                 :            :         }
     363                 :            : }
     364                 :            : 
     365                 :          0 : void delete_link_remaps(void) { __rollback_link_remaps(true); }
     366                 :        896 : void free_link_remaps(void) { __rollback_link_remaps(false); }
     367                 :            : 
     368                 :          4 : static int create_link_remap(char *path, int len, int lfd,
     369                 :            :                                 u32 *idp, struct ns_id *nsid)
     370                 :            : {
     371                 :            :         char link_name[PATH_MAX], *tmp;
     372                 :          4 :         RegFileEntry rfe = REG_FILE_ENTRY__INIT;
     373                 :          4 :         FownEntry fwn = FOWN_ENTRY__INIT;
     374                 :            :         struct link_remap_rlb *rlb;
     375                 :            :         int mntns_root;
     376                 :            : 
     377         [ -  + ]:          4 :         if (!opts.link_remap_ok) {
     378                 :          0 :                 pr_err("Can't create link remap for %s. "
     379                 :            :                                 "Use " LREMAP_PARAM " option.\n", path);
     380                 :            :                 return -1;
     381                 :            :         }
     382                 :            : 
     383                 :            :         /*
     384                 :            :          * Linked remapping -- we create a hard link on a removed file
     385                 :            :          * in the directory original file used to sit.
     386                 :            :          *
     387                 :            :          * Bad news is than we can't easily open lfd's parent dir. Thus
     388                 :            :          * we have to just generate an absolute path and use it. The linkat
     389                 :            :          * will fail if we chose the bad one.
     390                 :            :          */
     391                 :            : 
     392                 :          4 :         link_name[0] = '.';
     393                 :          4 :         memcpy(link_name + 1, path, len);
     394                 :          4 :         tmp = link_name + len + 1;
     395         [ +  + ]:        124 :         while (*tmp != '/') {
     396         [ -  + ]:        120 :                 BUG_ON(tmp == link_name);
     397                 :        120 :                 tmp--;
     398                 :            :         }
     399                 :            : 
     400                 :          4 :         fd_id_generate_special(NULL, idp);
     401                 :          4 :         rfe.id          = *idp;
     402                 :          4 :         rfe.flags       = 0;
     403                 :          4 :         rfe.pos         = 0;
     404                 :          4 :         rfe.fown        = &fwn;
     405                 :          4 :         rfe.name        = link_name + 1;
     406                 :            : 
     407                 :            :         /* Any 'unique' name works here actually. Remap works by reg-file ids. */
     408                 :          4 :         snprintf(tmp + 1, sizeof(link_name) - (size_t)(tmp - link_name - 1), "link_remap.%d", rfe.id);
     409                 :            : 
     410                 :          4 :         mntns_root = mntns_collect_root(nsid->pid);
     411                 :            : 
     412         [ -  + ]:          4 :         if (linkat(lfd, "", mntns_root, link_name, AT_EMPTY_PATH) < 0) {
     413                 :          0 :                 pr_perror("Can't link remap to %s", path);
     414                 :            :                 return -1;
     415                 :            :         }
     416                 :            : 
     417                 :            :         /*
     418                 :            :          * Remember the name to delete it if needed on error or
     419                 :            :          * rollback action. Note we don't expect that there will
     420                 :            :          * be a HUGE number of link remaps, so in a sake of speed
     421                 :            :          * we keep all data in memory.
     422                 :            :          */
     423         [ -  + ]:          4 :         rlb = xmalloc(sizeof(*rlb));
     424         [ +  - ]:          4 :         if (rlb)
     425                 :          4 :                 rlb->path = strdup(link_name);
     426                 :            : 
     427                 :          4 :         rlb->pid = nsid->pid;
     428                 :            : 
     429 [ +  - ][ -  + ]:          4 :         if (!rlb || !rlb->path) {
     430                 :          0 :                 pr_perror("Can't register rollback for %s", path);
     431 [ #  # ][ #  # ]:          0 :                 xfree(rlb ? rlb->path : NULL);
                 [ #  # ]
     432         [ #  # ]:          0 :                 xfree(rlb);
     433                 :            :                 return -1;
     434                 :            :         }
     435                 :          4 :         list_add(&rlb->list, &link_remaps);
     436                 :            : 
     437                 :          4 :         return pb_write_one(fdset_fd(glob_fdset, CR_FD_REG_FILES), &rfe, PB_REG_FILE);
     438                 :            : }
     439                 :            : 
     440                 :          8 : static int dump_linked_remap(char *path, int len, const struct stat *ost,
     441                 :            :                                 int lfd, u32 id, struct ns_id *nsid)
     442                 :            : {
     443                 :            :         u32 lid;
     444                 :          4 :         RemapFilePathEntry rpe = REMAP_FILE_PATH_ENTRY__INIT;
     445                 :            : 
     446         [ +  - ]:          4 :         if (create_link_remap(path, len, lfd, &lid, nsid))
     447                 :            :                 return -1;
     448                 :            : 
     449                 :          4 :         rpe.orig_id = id;
     450                 :          4 :         rpe.remap_id = lid;
     451                 :            : 
     452                 :          4 :         return pb_write_one(fdset_fd(glob_fdset, CR_FD_REMAP_FPATH),
     453                 :            :                         &rpe, PB_REMAP_FPATH);
     454                 :            : }
     455                 :            : 
     456                 :          0 : static bool is_sillyrename_name(char *name)
     457                 :            : {
     458                 :            :         int i;
     459                 :            : 
     460                 :          0 :         name = strrchr(name, '/');
     461         [ #  # ]:          0 :         BUG_ON(name == NULL); /* see check in dump_one_reg_file */
     462                 :          0 :         name++;
     463                 :            : 
     464                 :            :         /*
     465                 :            :          * Strictly speaking this check is not bullet-proof. User
     466                 :            :          * can create file with this name by hands and we have no
     467                 :            :          * API to distinguish really-silly-renamed files from those
     468                 :            :          * fake names :(
     469                 :            :          *
     470                 :            :          * But since NFS people expect .nfsXXX files to be unstable,
     471                 :            :          * we treat them as such too.
     472                 :            :          */
     473                 :            : 
     474         [ #  # ]:          0 :         if (strncmp(name, SILLYNAME_PREF, sizeof(SILLYNAME_PREF) - 1))
     475                 :            :                 return false;
     476                 :            : 
     477                 :          0 :         name += sizeof(SILLYNAME_PREF) - 1;
     478         [ #  # ]:          0 :         for (i = 0; i < SILLYNAME_SUFF_LEN; i++)
     479         [ #  # ]:          0 :                 if (!isxdigit(name[i]))
     480                 :            :                         return false;
     481                 :            : 
     482                 :            :         return true;
     483                 :            : }
     484                 :            : 
     485                 :            : static inline bool nfs_silly_rename(char *rpath, const struct fd_parms *parms)
     486                 :            : {
     487 [ -  + ][ #  # ]:       3844 :         return (parms->fs_type == NFS_SUPER_MAGIC) && is_sillyrename_name(rpath);
     488                 :            : }
     489                 :            : 
     490                 :       3884 : static int check_path_remap(char *rpath, int plen, const struct fd_parms *parms,
     491                 :            :                                 int lfd, u32 id, struct ns_id *nsid)
     492                 :            : {
     493                 :            :         int ret, mntns_root;
     494                 :            :         struct stat pst;
     495                 :       3884 :         const struct stat *ost = &parms->stat;
     496                 :            : 
     497         [ +  + ]:       3884 :         if (ost->st_nlink == 0)
     498                 :            :                 /*
     499                 :            :                  * Unpleasant, but easy case. File is completely invisible
     500                 :            :                  * from the FS. Just dump its contents and that's it. But
     501                 :            :                  * be careful whether anybody still has any of its hardlinks
     502                 :            :                  * also open.
     503                 :            :                  */
     504                 :         40 :                 return dump_ghost_remap(rpath + 1, ost, lfd, id, nsid);
     505                 :            : 
     506         [ -  + ]:       3844 :         if (nfs_silly_rename(rpath, parms)) {
     507                 :            :                 /*
     508                 :            :                  * If this is NFS silly-rename file the path we have at hands
     509                 :            :                  * will be accessible by fstat(), but once we kill the dumping
     510                 :            :                  * tasks it will disappear. So we just go ahead an dump it as
     511                 :            :                  * linked-remap file (NFS will allow us to create more hard
     512                 :            :                  * links on it) to have some persistent name at hands.
     513                 :            :                  */
     514                 :          0 :                 pr_debug("Dump silly-rename linked remap for %x\n", id);
     515                 :          0 :                 return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id, nsid);
     516                 :            :         }
     517                 :            : 
     518                 :       3844 :         mntns_root = mntns_collect_root(nsid->pid);
     519         [ +  - ]:       3844 :         if (mntns_root < 0)
     520                 :            :                 return -1;
     521                 :            : 
     522                 :            :         ret = fstatat(mntns_root, rpath, &pst, 0);
     523         [ +  + ]:       3844 :         if (ret < 0) {
     524                 :            :                 /*
     525                 :            :                  * Linked file, but path is not accessible (unless any
     526                 :            :                  * other error occurred). We can create a temporary link to it
     527                 :            :                  * uning linkat with AT_EMPTY_PATH flag and remap it to this
     528                 :            :                  * name.
     529                 :            :                  */
     530                 :            : 
     531         [ +  - ]:          4 :                 if (errno == ENOENT)
     532                 :          4 :                         return dump_linked_remap(rpath + 1, plen - 1,
     533                 :            :                                                         ost, lfd, id, nsid);
     534                 :            : 
     535                 :          0 :                 pr_perror("Can't stat path");
     536                 :          0 :                 return -1;
     537                 :            :         }
     538                 :            : 
     539 [ +  - ][ -  + ]:       3840 :         if ((pst.st_ino != ost->st_ino) || (pst.st_dev != ost->st_dev)) {
     540 [ #  # ][ #  # ]:          0 :                 if (opts.evasive_devices &&
     541         [ #  # ]:          0 :                     (S_ISCHR(ost->st_mode) || S_ISBLK(ost->st_mode)) &&
     542                 :          0 :                     pst.st_rdev == ost->st_rdev)
     543                 :            :                         return 0;
     544                 :            :                 /*
     545                 :            :                  * FIXME linked file, but the name we see it by is reused
     546                 :            :                  * by somebody else. We can dump it with linked remaps, but
     547                 :            :                  * we'll have difficulties on restore -- we will have to
     548                 :            :                  * move the exisint file aside, then restore this one,
     549                 :            :                  * unlink, then move the original file back. It's fairly
     550                 :            :                  * easy to do, but we don't do it now, since unlinked files
     551                 :            :                  * have the "(deleted)" suffix in proc and name conflict
     552                 :            :                  * is unlikely :)
     553                 :            :                  */
     554                 :          0 :                 pr_err("Unaccessible path opened %u:%u, need %u:%u\n",
     555                 :            :                                 (int)pst.st_dev, (int)pst.st_ino,
     556                 :            :                                 (int)ost->st_dev, (int)ost->st_ino);
     557                 :          0 :                 return -1;
     558                 :            :         }
     559                 :            : 
     560                 :            :         /*
     561                 :            :          * File is linked and visible by the name it is opened by
     562                 :            :          * this task. Go ahead and dump it.
     563                 :            :          */
     564                 :            :         return 0;
     565                 :            : }
     566                 :            : 
     567                 :       3884 : int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
     568                 :            : {
     569                 :            :         struct fd_link _link, *link;
     570                 :            :         struct ns_id *nsid;
     571                 :            :         int rfd;
     572                 :            : 
     573                 :       3884 :         RegFileEntry rfe = REG_FILE_ENTRY__INIT;
     574                 :            : 
     575         [ +  + ]:       3884 :         if (!p->link) {
     576         [ +  - ]:       3040 :                 if (fill_fdlink(lfd, p, &_link))
     577                 :            :                         return -1;
     578                 :            :                 link = &_link;
     579                 :            :         } else
     580                 :            :                 link = p->link;
     581                 :            : 
     582 [ -  + ][ #  # ]:       3884 :         if (p->mnt_id >= 0 && (root_ns_mask & CLONE_NEWNS)) {
     583         [ #  # ]:          0 :                 if (lookup_mnt_id(p->mnt_id) == NULL) {
     584                 :          0 :                         pr_err("No mount for the %d file in the namespaces\n", p->mnt_id);
     585                 :          0 :                         return -1;
     586                 :            :                 }
     587                 :            : 
     588                 :          0 :                 rfe.mnt_id = p->mnt_id;
     589                 :          0 :                 rfe.has_mnt_id = true;
     590                 :            :         }
     591                 :            : 
     592                 :       3884 :         nsid = lookup_nsid_by_mnt_id(p->mnt_id);
     593         [ -  + ]:       3884 :         if (nsid == NULL) {
     594                 :          0 :                 pr_err("Unable to look up the %d mount\n", p->mnt_id);
     595                 :          0 :                 return -1;
     596                 :            :         }
     597                 :            : 
     598                 :       3884 :         pr_info("Dumping path for %d fd via self %d [%s]\n",
     599                 :            :                         p->fd, lfd, &link->name[1]);
     600                 :            : 
     601                 :            :         /*
     602                 :            :          * The regular path we can handle should start with slash.
     603                 :            :          */
     604         [ -  + ]:       3884 :         if (link->name[1] != '/') {
     605                 :          0 :                 pr_err("The path [%s] is not supported\n", &link->name[1]);
     606                 :          0 :                 return -1;
     607                 :            :         }
     608                 :            : 
     609         [ +  - ]:       3884 :         if (check_path_remap(link->name, link->len, p, lfd, id, nsid))
     610                 :            :                 return -1;
     611                 :            : 
     612                 :       3884 :         rfe.id          = id;
     613                 :       3884 :         rfe.flags       = p->flags;
     614                 :       3884 :         rfe.pos         = p->pos;
     615                 :       3884 :         rfe.fown        = (FownEntry *)&p->fown;
     616                 :       3884 :         rfe.name        = &link->name[1];
     617                 :            : 
     618                 :       3884 :         rfd = fdset_fd(glob_fdset, CR_FD_REG_FILES);
     619                 :            : 
     620                 :       3884 :         return pb_write_one(rfd, &rfe, PB_REG_FILE);
     621                 :            : }
     622                 :            : 
     623                 :            : const struct fdtype_ops regfile_dump_ops = {
     624                 :            :         .type           = FD_TYPES__REG,
     625                 :            :         .dump           = dump_one_reg_file,
     626                 :            : };
     627                 :            : 
     628                 :            : /*
     629                 :            :  * This routine properly resolves d's path handling ghost/link-remaps.
     630                 :            :  * The open_cb is a routine that does actual open, it differs for
     631                 :            :  * files, directories, fifos, etc.
     632                 :            :  */
     633                 :            : 
     634                 :            : static inline int rfi_remap(struct reg_file_info *rfi)
     635                 :            : {
     636                 :         30 :         return link(rfi->remap->path, rfi->path);
     637                 :            : }
     638                 :            : 
     639                 :       6886 : int open_path(struct file_desc *d,
     640                 :            :                 int(*open_cb)(struct reg_file_info *, void *), void *arg)
     641                 :            : {
     642                 :         30 :         struct reg_file_info *rfi;
     643                 :            :         int tmp;
     644                 :            :         char *orig_path = NULL;
     645                 :            : 
     646                 :            :         rfi = container_of(d, struct reg_file_info, d);
     647                 :            : 
     648         [ +  + ]:       6886 :         if (rfi->remap) {
     649                 :         30 :                 mutex_lock(ghost_file_mutex);
     650         [ -  + ]:         30 :                 if (rfi_remap(rfi) < 0) {
     651                 :            :                         static char tmp_path[PATH_MAX];
     652                 :            : 
     653         [ #  # ]:          0 :                         if (errno != EEXIST) {
     654                 :          0 :                                 pr_perror("Can't link %s -> %s", rfi->path,
     655                 :            :                                                 rfi->remap->path);
     656                 :          0 :                                 return -1;
     657                 :            :                         }
     658                 :            : 
     659                 :            :                         /*
     660                 :            :                          * The file whose name we're trying to create
     661                 :            :                          * exists. Need to pick some other one, we're
     662                 :            :                          * going to remove it anyway.
     663                 :            :                          *
     664                 :            :                          * Strictly speaking, this is cheating, file
     665                 :            :                          * name shouldn't change. But since NFS with
     666                 :            :                          * its silly-rename doesn't care, why should we?
     667                 :            :                          */
     668                 :            : 
     669                 :          0 :                         orig_path = rfi->path;
     670                 :          0 :                         rfi->path = tmp_path;
     671                 :            :                         snprintf(tmp_path, sizeof(tmp_path), "%s.cr_link", orig_path);
     672                 :          0 :                         pr_debug("Fake %s -> %s link\n", rfi->path, rfi->remap->path);
     673                 :            : 
     674         [ #  # ]:          0 :                         if (rfi_remap(rfi) < 0) {
     675                 :          0 :                                 pr_perror("Can't create even fake link!");
     676                 :          0 :                                 return -1;
     677                 :            :                         }
     678                 :            :                 }
     679                 :            :         }
     680                 :            : 
     681                 :       6886 :         tmp = open_cb(rfi, arg);
     682         [ -  + ]:       6886 :         if (tmp < 0) {
     683                 :          0 :                 pr_perror("Can't open file %s", rfi->path);
     684                 :          0 :                 return -1;
     685                 :            :         }
     686                 :            : 
     687         [ +  + ]:       6886 :         if (rfi->remap) {
     688                 :         30 :                 unlink(rfi->path);
     689         [ -  + ]:         30 :                 BUG_ON(!rfi->remap->users);
     690         [ +  + ]:         30 :                 if (--rfi->remap->users == 0) {
     691                 :         18 :                         pr_info("Unlink the ghost %s\n", rfi->remap->path);
     692                 :         18 :                         unlink(rfi->remap->path);
     693                 :            :                 }
     694                 :            : 
     695         [ -  + ]:         30 :                 if (orig_path)
     696                 :          0 :                         rfi->path = orig_path;
     697                 :         30 :                 mutex_unlock(ghost_file_mutex);
     698                 :            :         }
     699                 :            : 
     700         [ +  - ]:       6886 :         if (restore_fown(tmp, rfi->rfe->fown))
     701                 :            :                 return -1;
     702                 :            : 
     703                 :       6886 :         return tmp;
     704                 :            : }
     705                 :            : 
     706                 :       6872 : static int do_open_reg_noseek_flags(struct reg_file_info *rfi, void *arg)
     707                 :            : {
     708                 :       6872 :         u32 flags = *(u32 *)arg;
     709                 :            :         int fd, mntns_root;
     710                 :            :         struct ns_id *nsid;
     711                 :            : 
     712                 :       6872 :         nsid = lookup_nsid_by_mnt_id(rfi->rfe->mnt_id);
     713         [ +  - ]:       6872 :         if (nsid == NULL)
     714                 :            :                 return -1;
     715                 :            : 
     716                 :       6872 :         mntns_root = mntns_collect_root(nsid->pid);
     717                 :            : 
     718                 :       6872 :         fd = openat(mntns_root, rfi->path, flags);
     719         [ -  + ]:       6872 :         if (fd < 0) {
     720                 :          0 :                 pr_perror("Can't open file %s on restore", rfi->path);
     721                 :          0 :                 return fd;
     722                 :            :         }
     723                 :            : 
     724                 :            :         return fd;
     725                 :            : }
     726                 :            : 
     727                 :       1044 : static int do_open_reg_noseek(struct reg_file_info *rfi, void *arg)
     728                 :            : {
     729                 :       1606 :         return do_open_reg_noseek_flags(rfi, &rfi->rfe->flags);
     730                 :            : }
     731                 :            : 
     732                 :        562 : static int do_open_reg(struct reg_file_info *rfi, void *arg)
     733                 :            : {
     734                 :            :         int fd;
     735                 :            : 
     736                 :            :         fd = do_open_reg_noseek(rfi, arg);
     737         [ +  - ]:        562 :         if (fd < 0)
     738                 :            :                 return fd;
     739                 :            : 
     740   [ +  -  -  + ]:       1124 :         if ((rfi->rfe->pos != -1ULL) &&
     741                 :        562 :                         lseek(fd, rfi->rfe->pos, SEEK_SET) < 0) {
     742                 :          0 :                 pr_perror("Can't restore file pos");
     743                 :          0 :                 close(fd);
     744                 :          0 :                 return -1;
     745                 :            :         }
     746                 :            : 
     747                 :        562 :         return fd;
     748                 :            : }
     749                 :            : 
     750                 :       1044 : int open_reg_by_id(u32 id)
     751                 :            : {
     752                 :            :         struct file_desc *fd;
     753                 :            : 
     754                 :            :         /*
     755                 :            :          * This one gets called by exe link, chroot and cwd
     756                 :            :          * restoring code. No need in calling lseek on either
     757                 :            :          * of them.
     758                 :            :          */
     759                 :            : 
     760                 :       1044 :         fd = find_file_desc_raw(FD_TYPES__REG, id);
     761         [ -  + ]:       1044 :         if (fd == NULL) {
     762                 :          0 :                 pr_err("Can't find regfile for %#x\n", id);
     763                 :          0 :                 return -1;
     764                 :            :         }
     765                 :            : 
     766                 :       1044 :         return open_path(fd, do_open_reg_noseek, NULL);
     767                 :            : }
     768                 :            : 
     769                 :       5266 : int get_filemap_fd(struct vma_area *vma)
     770                 :            : {
     771                 :            :         u32 flags;
     772                 :            : 
     773                 :            :         /*
     774                 :            :          * Thevma->fd should have been assigned in collect_filemap
     775                 :            :          *
     776                 :            :          * We open file w/o lseek, as mappings don't care about it
     777                 :            :          */
     778                 :            : 
     779         [ -  + ]:       5266 :         BUG_ON(vma->fd == NULL);
     780         [ +  - ]:       5266 :         if (vma->e->has_fdflags)
     781                 :       5266 :                 flags = vma->e->fdflags;
     782 [ #  # ][ #  # ]:          0 :         else if ((vma->e->prot & PROT_WRITE) &&
     783                 :          0 :                         vma_area_is(vma, VMA_FILE_SHARED))
     784                 :          0 :                 flags = O_RDWR;
     785                 :            :         else
     786                 :          0 :                 flags = O_RDONLY;
     787                 :            : 
     788                 :       5266 :         return open_path(vma->fd, do_open_reg_noseek_flags, &flags);
     789                 :            : }
     790                 :            : 
     791                 :      12669 : static void remap_get(struct file_desc *fdesc, char typ)
     792                 :            : {
     793                 :            :         struct reg_file_info *rfi;
     794                 :            : 
     795                 :            :         rfi = container_of(fdesc, struct reg_file_info, d);
     796         [ +  + ]:      12669 :         if (rfi->remap) {
     797                 :         34 :                 pr_debug("One more remap user (%c) for %s\n",
     798                 :            :                                 typ, rfi->remap->path);
     799                 :            :                 /* No lock, we're still sngle-process here */
     800                 :         34 :                 rfi->remap->users++;
     801                 :            :         }
     802                 :      12669 : }
     803                 :            : 
     804                 :       3330 : static void collect_reg_fd(struct file_desc *fdesc,
     805                 :            :                 struct fdinfo_list_entry *fle, struct rst_info *ri)
     806                 :            : {
     807         [ +  + ]:       3330 :         if (list_empty(&fdesc->fd_info_head))
     808                 :       1154 :                 remap_get(fdesc, 'f');
     809                 :            : 
     810                 :            :         collect_gen_fd(fle, ri);
     811                 :       3330 : }
     812                 :            : 
     813                 :        562 : static int open_fe_fd(struct file_desc *fd)
     814                 :            : {
     815                 :        562 :         return open_path(fd, do_open_reg, NULL);
     816                 :            : }
     817                 :            : 
     818                 :            : static struct file_desc_ops reg_desc_ops = {
     819                 :            :         .type = FD_TYPES__REG,
     820                 :            :         .open = open_fe_fd,
     821                 :            :         .collect_fd = collect_reg_fd,
     822                 :            : };
     823                 :            : 
     824                 :      11515 : struct file_desc *collect_special_file(u32 id)
     825                 :            : {
     826                 :            :         struct file_desc *fdesc;
     827                 :            : 
     828                 :            :         /*
     829                 :            :          * Files dumped for vmas/exe links can have remaps
     830                 :            :          * configured. Need to bump-up users for them, otherwise
     831                 :            :          * the open_path() would unlink the remap file after
     832                 :            :          * the very first open.
     833                 :            :          */
     834                 :            : 
     835                 :      11515 :         fdesc = find_file_desc_raw(FD_TYPES__REG, id);
     836         [ -  + ]:      11515 :         if (fdesc == NULL) {
     837                 :          0 :                 pr_err("No entry for reg-file-ID %#x\n", id);
     838                 :          0 :                 return NULL;
     839                 :            :         }
     840                 :            : 
     841                 :      11515 :         remap_get(fdesc, 's');
     842                 :      11515 :         return fdesc;
     843                 :            : }
     844                 :            : 
     845                 :       3061 : static int collect_one_regfile(void *o, ProtobufCMessage *base)
     846                 :            : {
     847                 :            :         struct reg_file_info *rfi = o;
     848                 :            : 
     849                 :       3061 :         rfi->rfe = pb_msg(base, RegFileEntry);
     850                 :       3061 :         rfi->path = rfi->rfe->name;
     851                 :       3061 :         rfi->remap = NULL;
     852                 :            : 
     853                 :       3061 :         pr_info("Collected [%s] ID %#x\n", rfi->path, rfi->rfe->id);
     854                 :       3061 :         return file_desc_add(&rfi->d, rfi->rfe->id, &reg_desc_ops);
     855                 :            : }
     856                 :            : 
     857                 :            : struct collect_image_info reg_file_cinfo = {
     858                 :            :         .fd_type = CR_FD_REG_FILES,
     859                 :            :         .pb_type = PB_REG_FILE,
     860                 :            :         .priv_size = sizeof(struct reg_file_info),
     861                 :            :         .collect = collect_one_regfile,
     862                 :            : };
     863                 :            : 
     864                 :        355 : int prepare_shared_reg_files(void)
     865                 :            : {
     866                 :        355 :         ghost_file_mutex = shmalloc(sizeof(*ghost_file_mutex));
     867         [ +  - ]:        355 :         if (!ghost_file_mutex)
     868                 :            :                 return -1;
     869                 :            : 
     870                 :            :         mutex_init(ghost_file_mutex);
     871                 :        355 :         return 0;
     872                 :            : }

Generated by: LCOV version 1.9