LCOV - code coverage report
Current view: top level - home/snorch/criu - files.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 361 429 84.1 %
Date: 2014-04-22 Functions: 34 34 100.0 %
Branches: 200 294 68.0 %

           Branch data     Line data    Source code
       1                 :            : #include <unistd.h>
       2                 :            : #include <fcntl.h>
       3                 :            : #include <errno.h>
       4                 :            : 
       5                 :            : #include <linux/limits.h>
       6                 :            : #include <linux/major.h>
       7                 :            : 
       8                 :            : #include <sys/types.h>
       9                 :            : #include <sys/prctl.h>
      10                 :            : #include <sys/mman.h>
      11                 :            : #include <sys/stat.h>
      12                 :            : #include <sys/socket.h>
      13                 :            : #include <sys/un.h>
      14                 :            : #include <stdlib.h>
      15                 :            : 
      16                 :            : #include "files.h"
      17                 :            : #include "file-ids.h"
      18                 :            : #include "files-reg.h"
      19                 :            : #include "image.h"
      20                 :            : #include "list.h"
      21                 :            : #include "util.h"
      22                 :            : #include "util-pie.h"
      23                 :            : #include "lock.h"
      24                 :            : #include "sockets.h"
      25                 :            : #include "pstree.h"
      26                 :            : #include "tty.h"
      27                 :            : #include "pipes.h"
      28                 :            : #include "fifo.h"
      29                 :            : #include "eventfd.h"
      30                 :            : #include "eventpoll.h"
      31                 :            : #include "fsnotify.h"
      32                 :            : #include "signalfd.h"
      33                 :            : #include "namespaces.h"
      34                 :            : #include "tun.h"
      35                 :            : #include "fdset.h"
      36                 :            : #include "fs-magic.h"
      37                 :            : #include "proc_parse.h"
      38                 :            : 
      39                 :            : #include "parasite.h"
      40                 :            : #include "parasite-syscall.h"
      41                 :            : 
      42                 :            : #include "protobuf.h"
      43                 :            : #include "protobuf/fs.pb-c.h"
      44                 :            : #include "protobuf/ext-file.pb-c.h"
      45                 :            : 
      46                 :            : #include "plugin.h"
      47                 :            : 
      48                 :            : #define FDESC_HASH_SIZE 64
      49                 :            : static struct hlist_head file_desc_hash[FDESC_HASH_SIZE];
      50                 :            : 
      51                 :       1013 : int prepare_shared_fdinfo(void)
      52                 :            : {
      53                 :            :         int i;
      54                 :            : 
      55         [ +  + ]:      65845 :         for (i = 0; i < FDESC_HASH_SIZE; i++)
      56                 :      64832 :                 INIT_HLIST_HEAD(&file_desc_hash[i]);
      57                 :            : 
      58                 :       1013 :         return 0;
      59                 :            : }
      60                 :            : 
      61                 :       3733 : int file_desc_add(struct file_desc *d, u32 id, struct file_desc_ops *ops)
      62                 :            : {
      63                 :       3733 :         d->id = id;
      64                 :       3733 :         d->ops = ops;
      65                 :       3733 :         INIT_LIST_HEAD(&d->fd_info_head);
      66                 :            : 
      67                 :       3733 :         hlist_add_head(&d->hash, &file_desc_hash[id % FDESC_HASH_SIZE]);
      68                 :            : 
      69                 :       3733 :         return 0; /* this is to make tail-calls in collect_one_foo look nice */
      70                 :            : }
      71                 :            : 
      72                 :      16865 : struct file_desc *find_file_desc_raw(int type, u32 id)
      73                 :            : {
      74                 :            :         struct file_desc *d;
      75                 :            :         struct hlist_head *chain;
      76                 :            : 
      77                 :      16865 :         chain = &file_desc_hash[id % FDESC_HASH_SIZE];
      78 [ +  - ][ +  - ]:      16893 :         hlist_for_each_entry(d, chain, hash)
                 [ +  - ]
      79 [ +  + ][ -  + ]:      16893 :                 if (d->ops->type == type && d->id == id)
      80                 :            :                         return d;
      81                 :            : 
      82                 :            :         return NULL;
      83                 :            : }
      84                 :            : 
      85                 :            : static inline struct file_desc *find_file_desc(FdinfoEntry *fe)
      86                 :            : {
      87                 :       4278 :         return find_file_desc_raw(fe->type, fe->id);
      88                 :            : }
      89                 :            : 
      90                 :            : /*
      91                 :            :  * A file may be shared between several file descriptors. E.g
      92                 :            :  * when doing a fork() every fd of a forker and respective fds
      93                 :            :  * of the child have such. Another way of getting shared files
      94                 :            :  * is by dup()-ing them or sending them via unix sockets in
      95                 :            :  * SCM_RIGHTS message.
      96                 :            :  *
      97                 :            :  * We restore this type of things in 3 steps (states[] below)
      98                 :            :  *
      99                 :            :  * 1. Prepare step.
     100                 :            :  *    Select which task will create the file (open() one, or
     101                 :            :  *    call any other syscall for than (socket, pipe, etc.). All
     102                 :            :  *    the others, that share one, create unix sockets under the
     103                 :            :  *    respective file descriptor (transport socket).
     104                 :            :  * 2. Open step.
     105                 :            :  *    The one who creates the file (the 'master') creates one,
     106                 :            :  *    then creates one more unix socket (transport) and sends the
     107                 :            :  *    created file over this socket to the other recepients.
     108                 :            :  * 3. Receive step.
     109                 :            :  *    Those, who wait for the file to appear, receive one via
     110                 :            :  *    the transport socket, then close the socket and dup() the
     111                 :            :  *    received file descriptor into its place.
     112                 :            :  *
     113                 :            :  * There's the 4th step in the states[] array -- the post_open
     114                 :            :  * one. This one is not about file-sharing resolving, but about
     115                 :            :  * doing something with a file using it's 'desired' fd. The
     116                 :            :  * thing is that while going the 3-step process above, the file
     117                 :            :  * may appear in variuos places in the task's fd table, and if
     118                 :            :  * we want to do something with it's _final_ descriptor value,
     119                 :            :  * we should wait for it to appear there. So the post_open is
     120                 :            :  * called when the file is finally set into its place.
     121                 :            :  */
     122                 :            : 
     123                 :       4659 : struct fdinfo_list_entry *file_master(struct file_desc *d)
     124                 :            : {
     125         [ -  + ]:       4659 :         if (list_empty(&d->fd_info_head)) {
     126                 :          0 :                 pr_err("Empty list on file desc id %#x\n", d->id);
     127                 :          0 :                 BUG();
     128                 :            :         }
     129                 :            : 
     130                 :       4659 :         return list_first_entry(&d->fd_info_head,
     131                 :            :                         struct fdinfo_list_entry, desc_list);
     132                 :            : }
     133                 :            : 
     134                 :        355 : void show_saved_files(void)
     135                 :            : {
     136                 :            :         int i;
     137                 :            :         struct file_desc *fd;
     138                 :            : 
     139                 :        355 :         pr_info("File descs:\n");
     140         [ +  + ]:      23075 :         for (i = 0; i < FDESC_HASH_SIZE; i++)
     141 [ +  + ][ +  + ]:      26343 :                 hlist_for_each_entry(fd, &file_desc_hash[i], hash) {
                 [ +  + ]
     142                 :            :                         struct fdinfo_list_entry *le;
     143                 :            : 
     144                 :       3623 :                         pr_info(" `- type %d ID %#x\n", fd->ops->type, fd->id);
     145         [ +  + ]:       7901 :                         list_for_each_entry(le, &fd->fd_info_head, desc_list)
     146                 :       4278 :                                 pr_info("   `- FD %d pid %d\n", le->fe->fd, le->pid);
     147                 :            :                 }
     148                 :        355 : }
     149                 :            : 
     150                 :            : /*
     151                 :            :  * The gen_id thing is used to optimize the comparison of shared files.
     152                 :            :  * If two files have different gen_ids, then they are different for sure.
     153                 :            :  * If it matches, we don't know it and have to call sys_kcmp().
     154                 :            :  *
     155                 :            :  * The kcmp-ids.c engine does this trick, see comments in it for more info.
     156                 :            :  */
     157                 :            : 
     158                 :            : static u32 make_gen_id(const struct fd_parms *p)
     159                 :            : {
     160                 :       3839 :         return ((u32)p->stat.st_dev) ^ ((u32)p->stat.st_ino) ^ ((u32)p->pos);
     161                 :            : }
     162                 :            : 
     163                 :       3839 : int do_dump_gen_file(struct fd_parms *p, int lfd,
     164                 :            :                 const struct fdtype_ops *ops, const int fdinfo)
     165                 :            : {
     166                 :       3839 :         FdinfoEntry e = FDINFO_ENTRY__INIT;
     167                 :            :         int ret = -1;
     168                 :            : 
     169                 :       3839 :         e.type  = ops->type;
     170                 :       3839 :         e.id    = make_gen_id(p);
     171                 :       3839 :         e.fd    = p->fd;
     172                 :       3839 :         e.flags = p->fd_flags;
     173                 :            : 
     174                 :       3839 :         ret = fd_id_generate(p->pid, &e, p);
     175         [ +  + ]:       3839 :         if (ret == 1) /* new ID generated */
     176                 :       2162 :                 ret = ops->dump(lfd, e.id, p);
     177                 :            : 
     178         [ +  - ]:       3839 :         if (ret < 0)
     179                 :            :                 return ret;
     180                 :            : 
     181                 :       3839 :         pr_info("fdinfo: type: 0x%2x flags: %#o/%#o pos: 0x%8"PRIx64" fd: %d\n",
     182                 :            :                 ops->type, p->flags, (int)p->fd_flags, p->pos, p->fd);
     183                 :            : 
     184                 :       3839 :         return pb_write_one(fdinfo, &e, PB_FDINFO);
     185                 :            : }
     186                 :            : 
     187                 :       5068 : int fill_fdlink(int lfd, const struct fd_parms *p, struct fd_link *link)
     188                 :            : {
     189                 :            :         int len;
     190                 :            : 
     191                 :       5068 :         link->name[0] = '.';
     192                 :            : 
     193                 :       5068 :         len = read_fd_link(lfd, &link->name[1], sizeof(link->name) - 1);
     194         [ -  + ]:       5068 :         if (len < 0) {
     195                 :          0 :                 pr_err("Can't read link for pid %d fd %d\n", p->pid, p->fd);
     196                 :          0 :                 return -1;
     197                 :            :         }
     198                 :            : 
     199                 :       5068 :         link->len = len + 1;
     200                 :       5068 :         return 0;
     201                 :            : }
     202                 :            : 
     203                 :       3839 : static int fill_fd_params(struct parasite_ctl *ctl, int fd, int lfd,
     204                 :            :                                 struct fd_opts *opts, struct fd_parms *p)
     205                 :            : {
     206                 :            :         int ret;
     207                 :            :         struct statfs fsbuf;
     208                 :       3839 :         struct fdinfo_common fdinfo = { .mnt_id = -1 };
     209                 :            : 
     210         [ -  + ]:       3839 :         if (fstat(lfd, &p->stat) < 0) {
     211                 :          0 :                 pr_perror("Can't stat fd %d", lfd);
     212                 :          0 :                 return -1;
     213                 :            :         }
     214                 :            : 
     215         [ -  + ]:       3839 :         if (fstatfs(lfd, &fsbuf) < 0) {
     216                 :          0 :                 pr_perror("Can't statfs fd %d", lfd);
     217                 :          0 :                 return -1;
     218                 :            :         }
     219                 :            : 
     220         [ +  - ]:       3839 :         if (parse_fdinfo(lfd, FD_TYPES__UND, NULL, &fdinfo))
     221                 :            :                 return -1;
     222                 :            : 
     223                 :       3839 :         p->fs_type   = fsbuf.f_type;
     224                 :       3839 :         p->ctl               = ctl;
     225                 :       3839 :         p->fd                = fd;
     226                 :       3839 :         p->pos               = fdinfo.pos;
     227                 :       3839 :         p->flags     = fdinfo.flags;
     228                 :       3839 :         p->mnt_id    = fdinfo.mnt_id;
     229                 :       3839 :         p->pid               = ctl->pid.real;
     230                 :       3839 :         p->fd_flags  = opts->flags;
     231                 :            : 
     232                 :       3839 :         fown_entry__init(&p->fown);
     233                 :            : 
     234                 :       3839 :         pr_info("%d fdinfo %d: pos: 0x%16"PRIx64" flags: %16o/%#x\n",
     235                 :            :                 ctl->pid.real, fd, p->pos, p->flags, (int)p->fd_flags);
     236                 :            : 
     237                 :       3839 :         ret = fcntl(lfd, F_GETSIG, 0);
     238         [ -  + ]:       3839 :         if (ret < 0) {
     239                 :          0 :                 pr_perror("Can't get owner signum on %d", lfd);
     240                 :          0 :                 return -1;
     241                 :            :         }
     242                 :       3839 :         p->fown.signum = ret;
     243                 :            : 
     244         [ +  + ]:       3839 :         if (opts->fown.pid == 0)
     245                 :            :                 return 0;
     246                 :            : 
     247                 :          8 :         p->fown.pid   = opts->fown.pid;
     248                 :          8 :         p->fown.pid_type = opts->fown.pid_type;
     249                 :          8 :         p->fown.uid   = opts->fown.uid;
     250                 :          8 :         p->fown.euid  = opts->fown.euid;
     251                 :            : 
     252                 :          8 :         return 0;
     253                 :            : }
     254                 :            : 
     255                 :            : static const struct fdtype_ops *get_misc_dev_ops(int minor)
     256                 :            : {
     257         [ #  # ]:          0 :         switch (minor) {
     258                 :            :         case TUN_MINOR:
     259                 :            :                 return &tunfile_dump_ops;
     260                 :            :         };
     261                 :            : 
     262                 :            :         return NULL;
     263                 :            : }
     264                 :            : 
     265                 :        965 : static int dump_chrdev(struct fd_parms *p, int lfd, const int fdinfo)
     266                 :            : {
     267                 :       1930 :         int maj = major(p->stat.st_rdev);
     268                 :            :         const struct fdtype_ops *ops;
     269                 :            : 
     270   [ +  -  +  + ]:        965 :         switch (maj) {
     271                 :            :         case MEM_MAJOR:
     272                 :            :                 ops = &regfile_dump_ops;
     273                 :            :                 break;
     274                 :            :         case TTYAUX_MAJOR:
     275                 :            :         case UNIX98_PTY_MASTER_MAJOR ... (UNIX98_PTY_MASTER_MAJOR + UNIX98_PTY_MAJOR_COUNT - 1):
     276                 :            :         case UNIX98_PTY_SLAVE_MAJOR:
     277                 :            :                 ops = &tty_dump_ops;
     278                 :         54 :                 break;
     279                 :            :         case MISC_MAJOR:
     280                 :          0 :                 ops = get_misc_dev_ops(minor(p->stat.st_rdev));
     281         [ #  # ]:          0 :                 if (ops)
     282                 :            :                         break;
     283                 :            :                 /* fallthrough */
     284                 :            :         default: {
     285                 :            :                 char more[32];
     286                 :            : 
     287                 :            :                 sprintf(more, "%d:%d", maj, minor(p->stat.st_rdev));
     288                 :          4 :                 return dump_unsupp_fd(p, lfd, fdinfo, "chr", more);
     289                 :            :         }
     290                 :            :         }
     291                 :            : 
     292                 :        961 :         return do_dump_gen_file(p, lfd, ops, fdinfo);
     293                 :            : }
     294                 :            : 
     295                 :       3839 : static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_opts *opts,
     296                 :            :                        const int fdinfo)
     297                 :            : {
     298                 :       3839 :         struct fd_parms p = FD_PARMS_INIT;
     299                 :            :         const struct fdtype_ops *ops;
     300                 :            : 
     301         [ -  + ]:       3839 :         if (fill_fd_params(ctl, fd, lfd, opts, &p) < 0) {
     302                 :          0 :                 pr_perror("Can't get stat on %d", fd);
     303                 :          0 :                 return -1;
     304                 :            :         }
     305                 :            : 
     306         [ +  + ]:       3839 :         if (S_ISSOCK(p.stat.st_mode))
     307                 :        228 :                 return dump_socket(&p, lfd, fdinfo);
     308                 :            : 
     309         [ +  + ]:       3611 :         if (S_ISCHR(p.stat.st_mode))
     310                 :        965 :                 return dump_chrdev(&p, lfd, fdinfo);
     311                 :            : 
     312         [ +  + ]:       2646 :         if (p.fs_type == ANON_INODE_FS_MAGIC) {
     313                 :            :                 char link[32];
     314                 :            : 
     315         [ +  - ]:         20 :                 if (read_fd_link(lfd, link, sizeof(link)) < 0)
     316                 :            :                         return -1;
     317                 :            : 
     318         [ +  + ]:         20 :                 if (is_eventfd_link(link))
     319                 :            :                         ops = &eventfd_dump_ops;
     320         [ +  + ]:         16 :                 else if (is_eventpoll_link(link))
     321                 :            :                         ops = &eventpoll_dump_ops;
     322         [ +  + ]:         12 :                 else if (is_inotify_link(link))
     323                 :            :                         ops = &inotify_dump_ops;
     324         [ +  + ]:          8 :                 else if (is_fanotify_link(link))
     325                 :            :                         ops = &fanotify_dump_ops;
     326         [ -  + ]:          4 :                 else if (is_signalfd_link(link))
     327                 :            :                         ops = &signalfd_dump_ops;
     328                 :            :                 else
     329                 :          0 :                         return dump_unsupp_fd(&p, lfd, fdinfo, "anon", link);
     330                 :            : 
     331                 :         20 :                 return do_dump_gen_file(&p, lfd, ops, fdinfo);
     332                 :            :         }
     333                 :            : 
     334         [ +  + ]:       2626 :         if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode)) {
     335                 :            :                 struct fd_link link;
     336                 :            : 
     337         [ +  - ]:       2028 :                 if (fill_fdlink(lfd, &p, &link))
     338                 :            :                         return -1;
     339                 :            : 
     340                 :       2028 :                 p.link = &link;
     341         [ +  + ]:       2028 :                 if (link.name[1] == '/')
     342                 :       2024 :                         return do_dump_gen_file(&p, lfd, &regfile_dump_ops, fdinfo);
     343                 :            : 
     344         [ +  - ]:          4 :                 if (check_ns_proc(&link))
     345                 :          4 :                         return do_dump_gen_file(&p, lfd, &nsfile_dump_ops, fdinfo);
     346                 :            : 
     347                 :       2028 :                 return dump_unsupp_fd(&p, lfd, fdinfo, "reg", link.name + 1);
     348                 :            :         }
     349                 :            : 
     350         [ +  - ]:        598 :         if (S_ISFIFO(p.stat.st_mode)) {
     351         [ +  + ]:        598 :                 if (p.fs_type == PIPEFS_MAGIC)
     352                 :            :                         ops = &pipe_dump_ops;
     353                 :            :                 else
     354                 :            :                         ops = &fifo_dump_ops;
     355                 :            : 
     356                 :        598 :                 return do_dump_gen_file(&p, lfd, ops, fdinfo);
     357                 :            :         }
     358                 :            : 
     359                 :          0 :         return dump_unsupp_fd(&p, lfd, fdinfo, "unknown", NULL);
     360                 :            : }
     361                 :            : 
     362                 :        907 : int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
     363                 :            :                 struct parasite_drain_fd *dfds)
     364                 :            : {
     365                 :            :         int *lfds, fdinfo;
     366                 :            :         struct fd_opts *opts;
     367                 :            :         int i, ret = -1;
     368                 :            : 
     369                 :        907 :         pr_info("\n");
     370                 :        907 :         pr_info("Dumping opened files (pid: %d)\n", ctl->pid.real);
     371                 :        907 :         pr_info("----------------------------------------\n");
     372                 :            : 
     373         [ -  + ]:        907 :         lfds = xmalloc(dfds->nr_fds * sizeof(int));
     374         [ +  - ]:        907 :         if (!lfds)
     375                 :            :                 goto err;
     376                 :            : 
     377         [ -  + ]:        907 :         opts = xmalloc(dfds->nr_fds * sizeof(struct fd_opts));
     378         [ +  - ]:        907 :         if (!opts)
     379                 :            :                 goto err1;
     380                 :            : 
     381                 :        907 :         ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts);
     382         [ +  - ]:        907 :         if (ret)
     383                 :            :                 goto err2;
     384                 :            : 
     385                 :        907 :         fdinfo = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
     386         [ +  - ]:        907 :         if (fdinfo < 0)
     387                 :            :                 goto err2;
     388                 :            : 
     389         [ +  + ]:       4746 :         for (i = 0; i < dfds->nr_fds; i++) {
     390                 :       3839 :                 ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, fdinfo);
     391                 :       3839 :                 close(lfds[i]);
     392         [ +  - ]:       3839 :                 if (ret)
     393                 :            :                         break;
     394                 :            :         }
     395                 :            : 
     396                 :        907 :         close(fdinfo);
     397                 :            : 
     398                 :        907 :         pr_info("----------------------------------------\n");
     399                 :            : err2:
     400         [ +  - ]:        907 :         xfree(opts);
     401                 :            : err1:
     402         [ +  - ]:        907 :         xfree(lfds);
     403                 :            : err:
     404                 :        907 :         return ret;
     405                 :            : }
     406                 :            : 
     407                 :      17055 : static int predump_one_fd(int pid, int fd)
     408                 :            : {
     409                 :            :         const struct fdtype_ops *ops;
     410                 :            :         char link[PATH_MAX], t[32];
     411                 :            :         int ret = 0;
     412                 :            : 
     413                 :            :         snprintf(t, sizeof(t), "/proc/%d/fd/%d", pid, fd);
     414                 :      17055 :         ret = readlink(t, link, sizeof(link));
     415         [ -  + ]:      17055 :         if (ret < 0) {
     416                 :          0 :                 pr_perror("Can't read link of fd %d", fd);
     417                 :          0 :                 return -1;
     418         [ -  + ]:      17055 :         } else if ((size_t)ret == sizeof(link)) {
     419                 :          0 :                 pr_err("Buffer for read link of fd %d is too small\n", fd);
     420                 :          0 :                 return -1;
     421                 :            :         }
     422                 :      17055 :         link[ret] = 0;
     423                 :            : 
     424                 :            :         ret = 0;
     425         [ +  + ]:      17055 :         if (is_inotify_link(link))
     426                 :            :                 ops = &inotify_dump_ops;
     427         [ +  + ]:      17043 :         else if (is_fanotify_link(link))
     428                 :            :                 ops = &fanotify_dump_ops;
     429                 :            :         else
     430                 :            :                 goto out;
     431                 :            : 
     432                 :         24 :         pr_debug("Pre-dumping %d's %d fd\n", pid, fd);
     433                 :         24 :         ret = ops->pre_dump(pid, fd);
     434                 :            : out:
     435                 :      17055 :         return ret;
     436                 :            : }
     437                 :            : 
     438                 :       2745 : int predump_task_files(int pid)
     439                 :            : {
     440                 :            :         struct dirent *de;
     441                 :            :         DIR *fd_dir;
     442                 :            :         int ret = -1;
     443                 :            : 
     444                 :       2745 :         pr_info("Pre-dump fds for %d)\n", pid);
     445                 :            : 
     446 [ -  + ][ +  - ]:       2745 :         fd_dir = opendir_proc(pid, "fd");
                 [ -  + ]
     447         [ +  - ]:       2745 :         if (!fd_dir)
     448                 :            :                 return -1;
     449                 :            : 
     450         [ +  + ]:      25290 :         while ((de = readdir(fd_dir))) {
     451         [ +  + ]:      22545 :                 if (dir_dots(de))
     452                 :       5490 :                         continue;
     453                 :            : 
     454         [ +  - ]:      22545 :                 if (predump_one_fd(pid, atoi(de->d_name)))
     455                 :            :                         goto out;
     456                 :            :         }
     457                 :            : 
     458                 :            :         ret = 0;
     459                 :            : out:
     460                 :       2745 :         closedir(fd_dir);
     461                 :       2745 :         return ret;
     462                 :            : }
     463                 :            : 
     464                 :       7200 : int restore_fown(int fd, FownEntry *fown)
     465                 :            : {
     466                 :            :         struct f_owner_ex owner;
     467                 :            :         uid_t uids[3];
     468                 :       7200 :         pid_t pid = getpid();
     469                 :            : 
     470         [ +  + ]:       7200 :         if (fown->signum) {
     471         [ -  + ]:          4 :                 if (fcntl(fd, F_SETSIG, fown->signum)) {
     472                 :          0 :                         pr_perror("%d: Can't set signal", pid);
     473                 :          0 :                         return -1;
     474                 :            :                 }
     475                 :            :         }
     476                 :            : 
     477                 :            :         /* May be untouched */
     478         [ +  + ]:       7200 :         if (!fown->pid)
     479                 :            :                 return 0;
     480                 :            : 
     481         [ -  + ]:          4 :         if (getresuid(&uids[0], &uids[1], &uids[2])) {
     482                 :          0 :                 pr_perror("%d: Can't get current UIDs", pid);
     483                 :          0 :                 return -1;
     484                 :            :         }
     485                 :            : 
     486         [ -  + ]:          4 :         if (setresuid(fown->uid, fown->euid, uids[2])) {
     487                 :          0 :                 pr_perror("%d: Can't set UIDs", pid);
     488                 :          0 :                 return -1;
     489                 :            :         }
     490                 :            : 
     491                 :          4 :         owner.type = fown->pid_type;
     492                 :          4 :         owner.pid = fown->pid;
     493                 :            : 
     494         [ -  + ]:          4 :         if (fcntl(fd, F_SETOWN_EX, &owner)) {
     495                 :          0 :                 pr_perror("%d: Can't setup %d file owner pid",
     496                 :            :                           pid, fd);
     497                 :          0 :                 return -1;
     498                 :            :         }
     499                 :            : 
     500         [ -  + ]:          4 :         if (setresuid(uids[0], uids[1], uids[2])) {
     501                 :          0 :                 pr_perror("%d: Can't revert UIDs back", pid);
     502                 :          0 :                 return -1;
     503                 :            :         }
     504                 :            : 
     505                 :            :         return 0;
     506                 :            : }
     507                 :            : 
     508                 :        316 : int rst_file_params(int fd, FownEntry *fown, int flags)
     509                 :            : {
     510         [ +  - ]:        316 :         if (set_fd_flags(fd, flags) < 0)
     511                 :            :                 return -1;
     512         [ +  - ]:        316 :         if (restore_fown(fd, fown) < 0)
     513                 :            :                 return -1;
     514                 :        316 :         return 0;
     515                 :            : }
     516                 :            : 
     517                 :       4278 : static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
     518                 :            : {
     519                 :            :         struct fdinfo_list_entry *le, *new_le;
     520                 :            :         struct file_desc *fdesc;
     521                 :            : 
     522                 :       4278 :         pr_info("Collect fdinfo pid=%d fd=%d id=%#x\n",
     523                 :            :                 pid, e->fd, e->id);
     524                 :            : 
     525                 :       4278 :         new_le = shmalloc(sizeof(*new_le));
     526         [ +  - ]:       4278 :         if (!new_le)
     527                 :            :                 return -1;
     528                 :            : 
     529                 :            :         futex_init(&new_le->real_pid);
     530                 :       4278 :         new_le->pid = pid;
     531                 :       4278 :         new_le->fe = e;
     532                 :            : 
     533                 :            :         fdesc = find_file_desc(e);
     534         [ -  + ]:       4278 :         if (fdesc == NULL) {
     535                 :          0 :                 pr_err("No file for fd %d id %#x\n", e->fd, e->id);
     536                 :          0 :                 return -1;
     537                 :            :         }
     538                 :            : 
     539         [ +  + ]:       8853 :         list_for_each_entry(le, &fdesc->fd_info_head, desc_list)
     540         [ +  + ]:       5911 :                 if (pid_rst_prio(new_le->pid, le->pid))
     541                 :            :                         break;
     542                 :            : 
     543         [ +  + ]:       4278 :         if (fdesc->ops->collect_fd)
     544                 :       3416 :                 fdesc->ops->collect_fd(fdesc, new_le, rst_info);
     545                 :            :         else
     546                 :            :                 collect_gen_fd(new_le, rst_info);
     547                 :            : 
     548                 :       4278 :         list_add_tail(&new_le->desc_list, &le->desc_list);
     549                 :       4278 :         new_le->desc = fdesc;
     550                 :            : 
     551                 :       4278 :         return 0;
     552                 :            : }
     553                 :            : 
     554                 :         12 : int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id)
     555                 :            : {
     556                 :            :         FdinfoEntry *e;
     557                 :            : 
     558         [ +  - ]:         12 :         if (!ctl_tty_id)
     559                 :            :                 return 0;
     560                 :            : 
     561                 :         12 :         pr_info("Requesting for ctl tty %#x into service fd\n", ctl_tty_id);
     562                 :            : 
     563         [ -  + ]:         12 :         e = xmalloc(sizeof(*e));
     564         [ +  - ]:         12 :         if (!e)
     565                 :            :                 return -1;
     566                 :            : 
     567                 :         12 :         fdinfo_entry__init(e);
     568                 :            : 
     569                 :         12 :         e->id                = ctl_tty_id;
     570                 :         12 :         e->fd                = reserve_service_fd(CTL_TTY_OFF);
     571                 :         12 :         e->type              = FD_TYPES__TTY;
     572                 :            : 
     573         [ -  + ]:         12 :         if (collect_fd(pid, e, rst_info)) {
     574         [ #  # ]:          0 :                 xfree(e);
     575                 :            :                 return -1;
     576                 :            :         }
     577                 :            : 
     578                 :            :         return 0;
     579                 :            : }
     580                 :            : 
     581                 :       1011 : int prepare_fd_pid(struct pstree_item *item)
     582                 :            : {
     583                 :            :         int fdinfo_fd, ret = 0;
     584                 :       1011 :         pid_t pid = item->pid.virt;
     585                 :       1011 :         struct rst_info *rst_info = item->rst;
     586                 :            : 
     587                 :            :         INIT_LIST_HEAD(&rst_info->fds);
     588                 :       1011 :         INIT_LIST_HEAD(&rst_info->eventpoll);
     589                 :       1011 :         INIT_LIST_HEAD(&rst_info->tty_slaves);
     590                 :            : 
     591         [ -  + ]:       1011 :         if (!fdinfo_per_id) {
     592                 :          0 :                 fdinfo_fd = open_image(CR_FD_FDINFO, O_RSTR | O_OPT, pid);
     593         [ #  # ]:        954 :                 if (fdinfo_fd < 0) {
     594         [ #  # ]:          0 :                         if (fdinfo_fd == -ENOENT)
     595                 :            :                                 return 0;
     596                 :          0 :                         return -1;
     597                 :            :                 }
     598                 :            :         } else {
     599         [ +  + ]:       1011 :                 if (item->ids == NULL) /* zombie */
     600                 :            :                         return 0;
     601                 :            : 
     602 [ +  + ][ +  + ]:        981 :                 if (item->rst->fdt && item->rst->fdt->pid != item->pid.virt)
     603                 :            :                         return 0;
     604                 :            : 
     605                 :        954 :                 fdinfo_fd = open_image(CR_FD_FDINFO, O_RSTR, item->ids->files_id);
     606         [ +  - ]:        954 :                 if (fdinfo_fd < 0)
     607                 :            :                         return -1;
     608                 :            :         }
     609                 :            : 
     610                 :            :         while (1) {
     611                 :            :                 FdinfoEntry *e;
     612                 :            : 
     613                 :       5220 :                 ret = pb_read_one_eof(fdinfo_fd, &e, PB_FDINFO);
     614         [ +  + ]:       5220 :                 if (ret <= 0)
     615                 :            :                         break;
     616                 :            : 
     617                 :       4266 :                 ret = collect_fd(pid, e, rst_info);
     618         [ -  + ]:       4266 :                 if (ret < 0) {
     619                 :          0 :                         fdinfo_entry__free_unpacked(e, NULL);
     620                 :          0 :                         break;
     621                 :            :                 }
     622                 :       4266 :         }
     623                 :            : 
     624                 :        954 :         close(fdinfo_fd);
     625                 :        954 :         return ret;
     626                 :            : }
     627                 :            : 
     628                 :            : #define SETFL_MASK (O_APPEND | O_ASYNC | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
     629                 :        316 : int set_fd_flags(int fd, int flags)
     630                 :            : {
     631                 :            :         int ret;
     632                 :            : 
     633                 :        316 :         ret = fcntl(fd, F_GETFL, 0);
     634         [ +  - ]:        316 :         if (ret < 0)
     635                 :            :                 goto err;
     636                 :            : 
     637                 :        316 :         flags = (SETFL_MASK & flags) | (ret & ~SETFL_MASK);
     638                 :            : 
     639                 :        316 :         ret = fcntl(fd, F_SETFL, flags);
     640         [ -  + ]:        316 :         if (ret < 0)
     641                 :            :                 goto err;
     642                 :            :         return 0;
     643                 :            : 
     644                 :            : err:
     645                 :          0 :         pr_perror("fcntl call on fd %d (flags %x) failed", fd, flags);
     646                 :          0 :         return -1;
     647                 :            : }
     648                 :            : 
     649                 :            : struct fd_open_state {
     650                 :            :         char *name;
     651                 :            :         int (*cb)(int, struct fdinfo_list_entry *);
     652                 :            : 
     653                 :            :         /*
     654                 :            :          * Two last stages -- receive fds and post-open them -- are
     655                 :            :          * not required always. E.g. if no fd sharing takes place
     656                 :            :          * or task doens't have any files that need to be post-opened.
     657                 :            :          *
     658                 :            :          * Thus, in order not to scan through fdinfo-s lists in vain
     659                 :            :          * and speed things up a little bit, we may want to skeep these.
     660                 :            :          */
     661                 :            :         bool required;
     662                 :            : };
     663                 :            : 
     664                 :            : static int open_transport_fd(int pid, struct fdinfo_list_entry *fle);
     665                 :            : static int open_fd(int pid, struct fdinfo_list_entry *fle);
     666                 :            : static int receive_fd(int pid, struct fdinfo_list_entry *fle);
     667                 :            : static int post_open_fd(int pid, struct fdinfo_list_entry *fle);
     668                 :            : 
     669                 :            : static struct fd_open_state states[] = {
     670                 :            :         { "prepare",          open_transport_fd,      true,},
     671                 :            :         { "create",           open_fd,                true,},
     672                 :            :         { "receive",          receive_fd,             false,},
     673                 :            :         { "post_create",      post_open_fd,           false,},
     674                 :            : };
     675                 :            : 
     676                 :            : #define want_recv_stage()       do { states[2].required = true; } while (0)
     677                 :            : #define want_post_open_stage()  do { states[3].required = true; } while (0)
     678                 :            : 
     679                 :       1074 : static void transport_name_gen(struct sockaddr_un *addr, int *len,
     680                 :            :                 int pid, int fd)
     681                 :            : {
     682                 :       1074 :         addr->sun_family = AF_UNIX;
     683                 :       1074 :         snprintf(addr->sun_path, UNIX_PATH_MAX, "x/crtools-fd-%d-%d", pid, fd);
     684                 :       1074 :         *len = SUN_LEN(addr);
     685                 :       1074 :         *addr->sun_path = '\0';
     686                 :       1074 : }
     687                 :            : 
     688                 :            : static int should_open_transport(FdinfoEntry *fe, struct file_desc *fd)
     689                 :            : {
     690         [ +  + ]:        894 :         if (fd->ops->want_transport)
     691                 :        228 :                 return fd->ops->want_transport(fe, fd);
     692                 :            :         else
     693                 :            :                 return 0;
     694                 :            : }
     695                 :            : 
     696                 :       1577 : static int open_transport_fd(int pid, struct fdinfo_list_entry *fle)
     697                 :            : {
     698                 :            :         struct fdinfo_list_entry *flem;
     699                 :            :         struct sockaddr_un saddr;
     700                 :            :         int sock;
     701                 :            :         int ret, sun_len;
     702                 :            : 
     703                 :       1577 :         flem = file_master(fle->desc);
     704                 :            : 
     705         [ +  + ]:       1577 :         if (flem->pid == pid) {
     706         [ +  + ]:       1144 :                 if (flem->fe->fd != fle->fe->fd)
     707                 :            :                         /* dup-ed file. Will be opened in the open_fd */
     708                 :            :                         return 0;
     709                 :            : 
     710         [ +  + ]:        894 :                 if (!should_open_transport(fle->fe, fle->desc))
     711                 :            :                         /* pure master file */
     712                 :            :                         return 0;
     713                 :            : 
     714                 :            :                 /*
     715                 :            :                  * some master file, that wants a transport, e.g.
     716                 :            :                  * a pipe or unix socket pair 'slave' end
     717                 :            :                  */
     718                 :            :         }
     719                 :            : 
     720                 :        527 :         transport_name_gen(&saddr, &sun_len, getpid(), fle->fe->fd);
     721                 :            : 
     722                 :        527 :         pr_info("\t\tCreate transport fd %s\n", saddr.sun_path + 1);
     723                 :            : 
     724                 :            : 
     725                 :        527 :         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
     726         [ -  + ]:        527 :         if (sock < 0) {
     727                 :          0 :                 pr_perror("Can't create socket");
     728                 :          0 :                 return -1;
     729                 :            :         }
     730                 :        527 :         ret = bind(sock, &saddr, sun_len);
     731         [ -  + ]:        527 :         if (ret < 0) {
     732                 :          0 :                 pr_perror("Can't bind unix socket %s", saddr.sun_path + 1);
     733                 :          0 :                 return -1;
     734                 :            :         }
     735                 :            : 
     736                 :        527 :         ret = reopen_fd_as(fle->fe->fd, sock);
     737         [ +  - ]:        527 :         if (ret < 0)
     738                 :            :                 return -1;
     739                 :            : 
     740                 :        527 :         pr_info("\t\tWake up fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
     741                 :        527 :         futex_set_and_wake(&fle->real_pid, getpid());
     742                 :        527 :         want_recv_stage();
     743                 :            : 
     744                 :        527 :         return 0;
     745                 :            : }
     746                 :            : 
     747                 :        547 : int send_fd_to_peer(int fd, struct fdinfo_list_entry *fle, int sock)
     748                 :            : {
     749                 :            :         struct sockaddr_un saddr;
     750                 :            :         int len;
     751                 :            : 
     752                 :        547 :         pr_info("\t\tWait fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
     753                 :        547 :         futex_wait_while(&fle->real_pid, 0);
     754                 :        547 :         transport_name_gen(&saddr, &len,
     755                 :        547 :                         futex_get(&fle->real_pid), fle->fe->fd);
     756                 :        547 :         pr_info("\t\tSend fd %d to %s\n", fd, saddr.sun_path + 1);
     757                 :       1094 :         return send_fd(sock, &saddr, len, fd);
     758                 :            : }
     759                 :            : 
     760                 :       2288 : static int send_fd_to_self(int fd, struct fdinfo_list_entry *fle, int *sock)
     761                 :            : {
     762                 :       1144 :         int dfd = fle->fe->fd;
     763                 :            : 
     764         [ +  + ]:       1144 :         if (fd == dfd)
     765                 :            :                 return 0;
     766                 :            : 
     767                 :        250 :         pr_info("\t\t\tGoing to dup %d into %d\n", fd, dfd);
     768         [ +  - ]:        250 :         if (move_img_fd(sock, dfd))
     769                 :            :                 return -1;
     770                 :            : 
     771         [ -  + ]:        250 :         if (dup2(fd, dfd) != dfd) {
     772                 :          0 :                 pr_perror("Can't dup local fd %d -> %d", fd, dfd);
     773                 :            :                 return -1;
     774                 :            :         }
     775                 :            : 
     776         [ -  + ]:        250 :         if (fcntl(dfd, F_SETFD, fle->fe->flags) == -1) {
     777                 :          0 :                 pr_perror("Unable to set file descriptor flags");
     778                 :            :                 return -1;
     779                 :            :         }
     780                 :            : 
     781                 :            :         return 0;
     782                 :            : }
     783                 :            : 
     784                 :        374 : static int post_open_fd(int pid, struct fdinfo_list_entry *fle)
     785                 :            : {
     786                 :        374 :         struct file_desc *d = fle->desc;
     787                 :            : 
     788         [ +  + ]:        374 :         if (!d->ops->post_open)
     789                 :            :                 return 0;
     790                 :            : 
     791         [ +  + ]:        160 :         if (is_service_fd(fle->fe->fd, CTL_TTY_OFF))
     792                 :          8 :                 return d->ops->post_open(d, fle->fe->fd);
     793                 :            : 
     794         [ +  + ]:        152 :         if (fle != file_master(d))
     795                 :            :                 return 0;
     796                 :            : 
     797                 :        148 :         return d->ops->post_open(d, fle->fe->fd);
     798                 :            : }
     799                 :            : 
     800                 :            : 
     801                 :        894 : static int serve_out_fd(int pid, int fd, struct file_desc *d)
     802                 :            : {
     803                 :            :         int sock, ret;
     804                 :            :         struct fdinfo_list_entry *fle;
     805                 :            : 
     806                 :        894 :         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
     807         [ -  + ]:        894 :         if (sock < 0) {
     808                 :          0 :                 pr_perror("Can't create socket");
     809                 :          0 :                 return -1;
     810                 :            :         }
     811                 :            : 
     812                 :        894 :         pr_info("\t\tCreate fd for %d\n", fd);
     813                 :            : 
     814         [ +  + ]:       2483 :         list_for_each_entry(fle, &d->fd_info_head, desc_list) {
     815         [ +  + ]:       1589 :                 if (pid == fle->pid)
     816                 :       1144 :                         ret = send_fd_to_self(fd, fle, &sock);
     817                 :            :                 else
     818                 :        445 :                         ret = send_fd_to_peer(fd, fle, sock);
     819                 :            : 
     820         [ -  + ]:       1589 :                 if (ret) {
     821                 :          0 :                         pr_err("Can't sent fd %d to %d\n", fd, fle->pid);
     822                 :          0 :                         return -1;
     823                 :            :                 }
     824                 :            :         }
     825                 :            : 
     826                 :        894 :         close(sock);
     827                 :        894 :         return 0;
     828                 :            : }
     829                 :            : 
     830                 :       1577 : static int open_fd(int pid, struct fdinfo_list_entry *fle)
     831                 :            : {
     832                 :       1577 :         struct file_desc *d = fle->desc;
     833                 :            :         int new_fd;
     834                 :            : 
     835         [ +  + ]:       1577 :         if (d->ops->post_open)
     836                 :        160 :                 want_post_open_stage();
     837                 :            : 
     838         [ +  + ]:       1577 :         if (fle != file_master(d))
     839                 :            :                 return 0;
     840                 :            : 
     841                 :        894 :         new_fd = d->ops->open(d);
     842         [ +  - ]:        894 :         if (new_fd < 0)
     843                 :            :                 return -1;
     844                 :            : 
     845         [ +  - ]:        894 :         if (reopen_fd_as(fle->fe->fd, new_fd))
     846                 :            :                 return -1;
     847                 :            : 
     848         [ -  + ]:        894 :         if (fcntl(fle->fe->fd, F_SETFD, fle->fe->flags) == -1) {
     849                 :          0 :                 pr_perror("Unable to set file descriptor flags");
     850                 :          0 :                 return -1;
     851                 :            :         }
     852                 :            : 
     853                 :        894 :         return serve_out_fd(pid, fle->fe->fd, d);
     854                 :            : }
     855                 :            : 
     856                 :        767 : static int receive_fd(int pid, struct fdinfo_list_entry *fle)
     857                 :            : {
     858                 :            :         int tmp;
     859                 :            :         struct fdinfo_list_entry *flem;
     860                 :            : 
     861                 :        767 :         flem = file_master(fle->desc);
     862         [ +  + ]:        767 :         if (flem->pid == pid)
     863                 :            :                 return 0;
     864                 :            : 
     865                 :        433 :         pr_info("\tReceive fd for %d\n", fle->fe->fd);
     866                 :            : 
     867                 :        433 :         tmp = recv_fd(fle->fe->fd);
     868         [ -  + ]:        433 :         if (tmp < 0) {
     869                 :          0 :                 pr_err("Can't get fd %d\n", tmp);
     870                 :          0 :                 return -1;
     871                 :            :         }
     872                 :        433 :         close(fle->fe->fd);
     873                 :            : 
     874         [ +  - ]:        433 :         if (reopen_fd_as(fle->fe->fd, tmp) < 0)
     875                 :            :                 return -1;
     876                 :            : 
     877         [ -  + ]:        433 :         if (fcntl(fle->fe->fd, F_SETFD, fle->fe->flags) == -1) {
     878                 :          0 :                 pr_perror("Unable to set file descriptor flags");
     879                 :          0 :                 return -1;
     880                 :            :         }
     881                 :            : 
     882                 :            :         return 0;
     883                 :            : }
     884                 :            : 
     885                 :       4295 : static int open_fdinfo(int pid, struct fdinfo_list_entry *fle, int state)
     886                 :            : {
     887                 :       4295 :         pr_info("\tRestoring fd %d (state -> %s)\n",
     888                 :            :                         fle->fe->fd, states[state].name);
     889                 :       4295 :         return states[state].cb(pid, fle);
     890                 :            : }
     891                 :            : 
     892                 :       2691 : static int open_fdinfos(int pid, struct list_head *list, int state)
     893                 :            : {
     894                 :            :         int ret = 0;
     895                 :            :         struct fdinfo_list_entry *fle;
     896                 :            : 
     897         [ +  + ]:       6986 :         list_for_each_entry(fle, list, ps_list) {
     898                 :       4295 :                 ret = open_fdinfo(pid, fle, state);
     899         [ +  - ]:       4295 :                 if (ret)
     900                 :            :                         break;
     901                 :            :         }
     902                 :            : 
     903                 :       2691 :         return ret;
     904                 :            : }
     905                 :            : 
     906                 :        826 : int close_old_fds(struct pstree_item *me)
     907                 :            : {
     908                 :            :         DIR *dir;
     909                 :            :         struct dirent *de;
     910                 :            :         int fd, ret;
     911                 :            : 
     912 [ -  + ][ +  - ]:        826 :         dir = opendir_proc(getpid(), "fd");
                 [ -  + ]
     913         [ +  - ]:        826 :         if (dir == NULL)
     914                 :            :                 return -1;
     915                 :            : 
     916         [ +  + ]:       9345 :         while ((de = readdir(dir))) {
     917         [ +  + ]:       8519 :                 if (dir_dots(de))
     918                 :       1652 :                         continue;
     919                 :            : 
     920                 :       6867 :                 ret = sscanf(de->d_name, "%d", &fd);
     921         [ -  + ]:       6867 :                 if (ret != 1) {
     922                 :          0 :                         pr_err("Can't parse %s\n", de->d_name);
     923                 :          0 :                         return -1;
     924                 :            :                 }
     925                 :            : 
     926 [ +  + ][ +  + ]:       6867 :                 if ((!is_any_service_fd(fd)) && (dirfd(dir) != fd))
     927                 :       8519 :                         close_safe(&fd);
     928                 :            :         }
     929                 :            : 
     930                 :        826 :         closedir(dir);
     931                 :        826 :         close_pid_proc();
     932                 :            : 
     933                 :        826 :         return 0;
     934                 :            : }
     935                 :            : 
     936                 :        348 : int prepare_fds(struct pstree_item *me)
     937                 :            : {
     938                 :            :         u32 ret = 0;
     939                 :            :         int state;
     940                 :            : 
     941                 :        348 :         pr_info("Opening fdinfo-s\n");
     942                 :            : 
     943         [ +  + ]:        348 :         if (me->rst->fdt) {
     944                 :            :                 struct fdt *fdt = me->rst->fdt;
     945                 :            : 
     946                 :            :                 /*
     947                 :            :                  * Wait all tasks, who share a current fd table.
     948                 :            :                  * We should be sure, that nobody use any file
     949                 :            :                  * descriptor while fdtable is being restored.
     950                 :            :                  */
     951                 :          7 :                 futex_inc_and_wake(&fdt->fdt_lock);
     952                 :          7 :                 futex_wait_while_lt(&fdt->fdt_lock, fdt->nr);
     953                 :            : 
     954         [ +  + ]:        348 :                 if (fdt->pid != me->pid.virt) {
     955                 :          5 :                         pr_info("File descriptor table is shared with %d\n", fdt->pid);
     956                 :          5 :                         futex_wait_until(&fdt->fdt_lock, fdt->nr + 1);
     957                 :          5 :                         goto out;
     958                 :            :                 }
     959                 :            :         }
     960                 :            : 
     961         [ +  + ]:       1715 :         for (state = 0; state < ARRAY_SIZE(states); state++) {
     962         [ +  + ]:       1372 :                 if (!states[state].required) {
     963                 :        475 :                         pr_debug("Skipping %s fd stage\n", states[state].name);
     964                 :        475 :                         continue;
     965                 :            :                 }
     966                 :            : 
     967                 :        897 :                 ret = open_fdinfos(me->pid.virt, &me->rst->fds, state);
     968         [ +  - ]:        897 :                 if (ret)
     969                 :            :                         break;
     970                 :            : 
     971                 :            :                 /*
     972                 :            :                  * Now handle TTYs. Slaves are delayed to be sure masters
     973                 :            :                  * are already opened.
     974                 :            :                  */
     975                 :        897 :                 ret = open_fdinfos(me->pid.virt, &me->rst->tty_slaves, state);
     976         [ +  - ]:        897 :                 if (ret)
     977                 :            :                         break;
     978                 :            : 
     979                 :            :                 /*
     980                 :            :                  * The eventpoll descriptors require all the other ones
     981                 :            :                  * to be already restored, thus we store them in a separate
     982                 :            :                  * list and restore at the very end.
     983                 :            :                  */
     984                 :        897 :                 ret = open_fdinfos(me->pid.virt, &me->rst->eventpoll, state);
     985         [ +  - ]:        897 :                 if (ret)
     986                 :            :                         break;
     987                 :            :         }
     988                 :            : 
     989         [ +  + ]:        343 :         if (me->rst->fdt)
     990                 :          2 :                 futex_inc_and_wake(&me->rst->fdt->fdt_lock);
     991                 :            : out:
     992                 :        348 :         close_service_fd(CR_PROC_FD_OFF);
     993                 :        348 :         tty_fini_fds();
     994                 :        348 :         return ret;
     995                 :            : }
     996                 :            : 
     997                 :        348 : static int fchroot(int fd)
     998                 :            : {
     999                 :            :         char fd_path[PSFDS];
    1000                 :            : 
    1001                 :            :         /*
    1002                 :            :          * There's no such thing in syscalls. We can emulate
    1003                 :            :          * it using the /proc/self/fd/ :)
    1004                 :            :          */
    1005                 :            : 
    1006                 :            :         sprintf(fd_path, "/proc/self/fd/%d", fd);
    1007                 :        348 :         pr_debug("Going to chroot into %s\n", fd_path);
    1008                 :        348 :         return chroot(fd_path);
    1009                 :            : }
    1010                 :            : 
    1011                 :        348 : int prepare_fs(int pid)
    1012                 :            : {
    1013                 :            :         int ifd, dd, ret = -1;
    1014                 :            :         FsEntry *fe;
    1015                 :            : 
    1016                 :        348 :         ifd = open_image(CR_FD_FS, O_RSTR, pid);
    1017         [ +  - ]:        348 :         if (ifd < 0)
    1018                 :            :                 goto out;
    1019                 :            : 
    1020         [ +  - ]:        348 :         if (pb_read_one(ifd, &fe, PB_FS) < 0)
    1021                 :            :                 goto out_i;
    1022                 :            : 
    1023                 :            :         /*
    1024                 :            :          * Restore CWD
    1025                 :            :          */
    1026                 :            : 
    1027                 :        348 :         dd = open_reg_by_id(fe->cwd_id);
    1028         [ -  + ]:        348 :         if (dd < 0) {
    1029                 :          0 :                 pr_err("Can't open cwd %#x\n", fe->cwd_id);
    1030                 :          0 :                 goto err;
    1031                 :            :         }
    1032                 :            : 
    1033                 :        348 :         ret = fchdir(dd);
    1034                 :        348 :         close(dd);
    1035         [ -  + ]:        348 :         if (ret < 0) {
    1036                 :          0 :                 pr_perror("Can't change cwd");
    1037                 :          0 :                 goto err;
    1038                 :            :         }
    1039                 :            : 
    1040                 :            :         /*
    1041                 :            :          * Restore root
    1042                 :            :          */
    1043                 :            : 
    1044                 :        348 :         dd = open_reg_by_id(fe->root_id);
    1045         [ -  + ]:        348 :         if (dd < 0) {
    1046                 :          0 :                 pr_err("Can't open root %#x\n", fe->root_id);
    1047                 :          0 :                 goto err;
    1048                 :            :         }
    1049                 :            : 
    1050                 :        348 :         ret = fchroot(dd);
    1051                 :        348 :         close(dd);
    1052         [ -  + ]:        348 :         if (ret < 0) {
    1053                 :          0 :                 pr_perror("Can't change root");
    1054                 :          0 :                 goto err;
    1055                 :            :         }
    1056                 :            : 
    1057         [ +  - ]:        348 :         if (fe->has_umask) {
    1058                 :        348 :                 pr_info("Restoring umask to %o\n", fe->umask);
    1059                 :        348 :                 umask(fe->umask);
    1060                 :            :         }
    1061                 :            : 
    1062                 :            :         ret = 0;
    1063                 :            : err:
    1064                 :        348 :         fs_entry__free_unpacked(fe, NULL);
    1065                 :            : out_i:
    1066                 :        348 :         close_safe(&ifd);
    1067                 :            : out:
    1068                 :        348 :         return ret;
    1069                 :            : }
    1070                 :            : 
    1071                 :         45 : int shared_fdt_prepare(struct pstree_item *item)
    1072                 :            : {
    1073                 :         45 :         struct pstree_item *parent = item->parent;
    1074                 :            :         struct fdt *fdt;
    1075                 :            : 
    1076         [ +  + ]:         45 :         if (!parent->rst->fdt) {
    1077                 :         15 :                 fdt = shmalloc(sizeof(*item->rst->fdt));
    1078         [ +  - ]:         15 :                 if (fdt == NULL)
    1079                 :            :                         return -1;
    1080                 :            : 
    1081                 :         15 :                 parent->rst->fdt = fdt;
    1082                 :            : 
    1083                 :            :                 futex_init(&fdt->fdt_lock);
    1084                 :         15 :                 fdt->nr = 1;
    1085                 :         15 :                 fdt->pid = parent->pid.virt;
    1086                 :            :         } else
    1087                 :            :                 fdt = parent->rst->fdt;
    1088                 :            : 
    1089                 :         45 :         item->rst->fdt = fdt;
    1090                 :         45 :         item->rst->service_fd_id = fdt->nr;
    1091                 :         45 :         fdt->nr++;
    1092         [ -  + ]:         45 :         if (pid_rst_prio(item->pid.virt, fdt->pid))
    1093                 :          0 :                 fdt->pid = item->pid.virt;
    1094                 :            : 
    1095                 :            :         return 0;
    1096                 :            : }

Generated by: LCOV version 1.9