LCOV - code coverage report
Current view: top level - crtools - files.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 213 237 89.9 %
Date: 2012-12-28 Functions: 25 25 100.0 %
Branches: 105 152 69.1 %

           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                 :            : 
       7                 :            : #include <sys/types.h>
       8                 :            : #include <sys/prctl.h>
       9                 :            : #include <sys/mman.h>
      10                 :            : #include <sys/stat.h>
      11                 :            : #include <sys/socket.h>
      12                 :            : #include <sys/un.h>
      13                 :            : #include <stdlib.h>
      14                 :            : 
      15                 :            : #include "crtools.h"
      16                 :            : 
      17                 :            : #include "files.h"
      18                 :            : #include "files-reg.h"
      19                 :            : #include "image.h"
      20                 :            : #include "list.h"
      21                 :            : #include "util.h"
      22                 :            : #include "util-net.h"
      23                 :            : #include "lock.h"
      24                 :            : #include "sockets.h"
      25                 :            : #include "pstree.h"
      26                 :            : #include "tty.h"
      27                 :            : 
      28                 :            : #include "protobuf.h"
      29                 :            : #include "protobuf/fs.pb-c.h"
      30                 :            : 
      31                 :            : #define FDESC_HASH_SIZE 64
      32                 :            : static struct list_head file_desc_hash[FDESC_HASH_SIZE];
      33                 :            : 
      34                 :        380 : int prepare_shared_fdinfo(void)
      35                 :            : {
      36                 :            :         int i;
      37                 :            : 
      38         [ +  + ]:      24700 :         for (i = 0; i < FDESC_HASH_SIZE; i++)
      39                 :      24320 :                 INIT_LIST_HEAD(&file_desc_hash[i]);
      40                 :            : 
      41                 :        380 :         return 0;
      42                 :            : }
      43                 :            : 
      44                 :      19751 : void file_desc_add(struct file_desc *d, u32 id, struct file_desc_ops *ops)
      45                 :            : {
      46                 :      19751 :         d->id = id;
      47                 :      19751 :         d->ops = ops;
      48                 :      19751 :         INIT_LIST_HEAD(&d->fd_info_head);
      49                 :            : 
      50                 :      19751 :         list_add_tail(&d->hash, &file_desc_hash[id % FDESC_HASH_SIZE]);
      51                 :      19751 : }
      52                 :            : 
      53                 :      12365 : struct file_desc *find_file_desc_raw(int type, u32 id)
      54                 :            : {
      55                 :            :         struct file_desc *d;
      56                 :            :         struct list_head *chain;
      57                 :            : 
      58                 :      12365 :         chain = &file_desc_hash[id % FDESC_HASH_SIZE];
      59         [ +  - ]:      26407 :         list_for_each_entry(d, chain, hash)
      60 [ +  + ][ +  + ]:      14042 :                 if (d->ops->type == type && d->id == id)
      61                 :            :                         return d;
      62                 :            : 
      63                 :            :         return NULL;
      64                 :            : }
      65                 :            : 
      66                 :            : static inline struct file_desc *find_file_desc(FdinfoEntry *fe)
      67                 :            : {
      68                 :       5898 :         return find_file_desc_raw(fe->type, fe->id);
      69                 :            : }
      70                 :            : 
      71                 :       5348 : struct fdinfo_list_entry *file_master(struct file_desc *d)
      72                 :            : {
      73         [ -  + ]:       5348 :         if (list_empty(&d->fd_info_head)) {
      74                 :          0 :                 pr_err("Empty list on file desc id %#x\n", d->id);
      75                 :          0 :                 BUG();
      76                 :            :         }
      77                 :            : 
      78                 :       5348 :         return list_first_entry(&d->fd_info_head,
      79                 :            :                         struct fdinfo_list_entry, desc_list);
      80                 :            : }
      81                 :            : 
      82                 :        355 : void show_saved_files(void)
      83                 :            : {
      84                 :            :         int i;
      85                 :            :         struct file_desc *fd;
      86                 :            : 
      87                 :        355 :         pr_info("File descs:\n");
      88         [ +  + ]:      23075 :         for (i = 0; i < FDESC_HASH_SIZE; i++)
      89         [ +  + ]:      42445 :                 list_for_each_entry(fd, &file_desc_hash[i], hash) {
      90                 :            :                         struct fdinfo_list_entry *le;
      91                 :            : 
      92                 :      19725 :                         pr_info(" `- type %d ID %#x\n", fd->ops->type, fd->id);
      93         [ +  + ]:      25623 :                         list_for_each_entry(le, &fd->fd_info_head, desc_list)
      94                 :       5898 :                                 pr_info("   `- FD %d pid %d\n", le->fe->fd, le->pid);
      95                 :            :                 }
      96                 :        355 : }
      97                 :            : 
      98                 :       7249 : int restore_fown(int fd, FownEntry *fown)
      99                 :            : {
     100                 :            :         struct f_owner_ex owner;
     101                 :            :         uid_t uids[3];
     102                 :       7249 :         pid_t pid = getpid();
     103                 :            : 
     104         [ +  + ]:       7249 :         if (fown->signum) {
     105         [ -  + ]:          2 :                 if (fcntl(fd, F_SETSIG, fown->signum)) {
     106                 :          0 :                         pr_perror("%d: Can't set signal", pid);
     107                 :            :                         return -1;
     108                 :            :                 }
     109                 :            :         }
     110                 :            : 
     111                 :            :         /* May be untouched */
     112         [ +  + ]:       7249 :         if (!fown->pid)
     113                 :            :                 return 0;
     114                 :            : 
     115         [ -  + ]:          2 :         if (getresuid(&uids[0], &uids[1], &uids[2])) {
     116                 :          0 :                 pr_perror("%d: Can't get current UIDs", pid);
     117                 :            :                 return -1;
     118                 :            :         }
     119                 :            : 
     120         [ -  + ]:          2 :         if (setresuid(fown->uid, fown->euid, uids[2])) {
     121                 :          0 :                 pr_perror("%d: Can't set UIDs", pid);
     122                 :            :                 return -1;
     123                 :            :         }
     124                 :            : 
     125                 :          2 :         owner.type = fown->pid_type;
     126                 :          2 :         owner.pid = fown->pid;
     127                 :            : 
     128         [ -  + ]:          2 :         if (fcntl(fd, F_SETOWN_EX, &owner)) {
     129                 :          0 :                 pr_perror("%d: Can't setup %d file owner pid",
     130                 :            :                           pid, fd);
     131                 :            :                 return -1;
     132                 :            :         }
     133                 :            : 
     134         [ -  + ]:          2 :         if (setresuid(uids[0], uids[1], uids[2])) {
     135                 :       7249 :                 pr_perror("%d: Can't revert UIDs back", pid);
     136                 :            :                 return -1;
     137                 :            :         }
     138                 :            : 
     139                 :            :         return 0;
     140                 :            : }
     141                 :            : 
     142                 :        196 : int rst_file_params(int fd, FownEntry *fown, int flags)
     143                 :            : {
     144         [ +  - ]:        196 :         if (set_fd_flags(fd, flags) < 0)
     145                 :            :                 return -1;
     146         [ +  - ]:        196 :         if (restore_fown(fd, fown) < 0)
     147                 :            :                 return -1;
     148                 :        196 :         return 0;
     149                 :            : }
     150                 :            : 
     151                 :            : static struct list_head *select_ps_list(struct file_desc *desc, struct rst_info *ri)
     152                 :            : {
     153         [ +  + ]:       5898 :         if (desc->ops->select_ps_list)
     154                 :         41 :                 return desc->ops->select_ps_list(desc, ri);
     155                 :            :         else
     156                 :       5857 :                 return &ri->fds;
     157                 :            : }
     158                 :            : 
     159                 :       5898 : static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
     160                 :            : {
     161                 :            :         struct fdinfo_list_entry *le, *new_le;
     162                 :            :         struct file_desc *fdesc;
     163                 :            : 
     164                 :       5898 :         pr_info("Collect fdinfo pid=%d fd=%d id=0x%16x\n",
     165                 :            :                 pid, e->fd, e->id);
     166                 :            : 
     167                 :       5898 :         new_le = shmalloc(sizeof(*new_le));
     168         [ +  - ]:       5898 :         if (!new_le)
     169                 :            :                 return -1;
     170                 :            : 
     171                 :       5898 :         futex_init(&new_le->real_pid);
     172                 :       5898 :         new_le->pid = pid;
     173                 :       5898 :         new_le->fe = e;
     174                 :            : 
     175                 :      17694 :         fdesc = find_file_desc(e);
     176         [ -  + ]:       5898 :         if (fdesc == NULL) {
     177                 :          0 :                 pr_err("No file for fd %d id %d\n", e->fd, e->id);
     178                 :          0 :                 return -1;
     179                 :            :         }
     180                 :            : 
     181         [ +  + ]:      14681 :         list_for_each_entry(le, &fdesc->fd_info_head, desc_list) {
     182         [ +  + ]:      10889 :                 if (le->pid > new_le->pid)
     183                 :            :                         break;
     184                 :            :         }
     185                 :            : 
     186                 :       5898 :         list_add_tail(&new_le->desc_list, &le->desc_list);
     187                 :       5898 :         new_le->desc = fdesc;
     188                 :       5898 :         list_add_tail(&new_le->ps_list, select_ps_list(fdesc, rst_info));
     189                 :            : 
     190                 :       5898 :         return 0;
     191                 :            : }
     192                 :            : 
     193                 :         10 : int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id)
     194                 :            : {
     195                 :            :         FdinfoEntry *e;
     196                 :            : 
     197         [ +  - ]:         10 :         if (!ctl_tty_id)
     198                 :            :                 return 0;
     199                 :            : 
     200                 :         10 :         pr_info("Requesting for ctl tty %#x into service fd\n", ctl_tty_id);
     201                 :            : 
     202         [ -  + ]:         10 :         e = xmalloc(sizeof(*e));
     203         [ +  - ]:         10 :         if (!e)
     204                 :            :                 return -1;
     205                 :            : 
     206                 :         10 :         fdinfo_entry__init(e);
     207                 :            : 
     208                 :         10 :         e->id                = ctl_tty_id;
     209                 :         10 :         e->fd                = get_service_fd(CTL_TTY_OFF);
     210                 :         10 :         e->type              = FD_TYPES__TTY;
     211                 :            : 
     212         [ -  + ]:         10 :         if (collect_fd(pid, e, rst_info)) {
     213         [ #  # ]:         10 :                 xfree(e);
     214                 :            :                 return -1;
     215                 :            :         }
     216                 :            : 
     217                 :            :         return 0;
     218                 :            : }
     219                 :            : 
     220                 :       1459 : int prepare_fd_pid(int pid, struct rst_info *rst_info)
     221                 :            : {
     222                 :       1459 :         int fdinfo_fd, ret = 0;
     223                 :            : 
     224                 :       1459 :         INIT_LIST_HEAD(&rst_info->fds);
     225                 :       1459 :         INIT_LIST_HEAD(&rst_info->eventpoll);
     226                 :       1459 :         INIT_LIST_HEAD(&rst_info->tty_slaves);
     227                 :            : 
     228                 :       1459 :         fdinfo_fd = open_image_ro(CR_FD_FDINFO, pid);
     229         [ +  + ]:       1459 :         if (fdinfo_fd < 0) {
     230         [ -  + ]:         33 :                 if (errno == ENOENT)
     231                 :            :                         return 0;
     232                 :            :                 else
     233                 :          0 :                         return -1;
     234                 :            :         }
     235                 :            : 
     236                 :            :         while (1) {
     237                 :            :                 FdinfoEntry *e;
     238                 :            : 
     239                 :       7314 :                 ret = pb_read_one_eof(fdinfo_fd, &e, PB_FDINFO);
     240         [ +  + ]:       7314 :                 if (ret <= 0)
     241                 :            :                         break;
     242                 :            : 
     243                 :       5888 :                 ret = collect_fd(pid, e, rst_info);
     244         [ -  + ]:       5888 :                 if (ret < 0) {
     245                 :          0 :                         fdinfo_entry__free_unpacked(e, NULL);
     246                 :            :                         break;
     247                 :            :                 }
     248                 :       5888 :         }
     249                 :            : 
     250                 :       1426 :         close(fdinfo_fd);
     251                 :       1459 :         return ret;
     252                 :            : }
     253                 :            : 
     254                 :            : #define SETFL_MASK (O_APPEND | O_ASYNC | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
     255                 :        196 : int set_fd_flags(int fd, int flags)
     256                 :            : {
     257                 :            :         int ret;
     258                 :            : 
     259                 :        196 :         ret = fcntl(fd, F_GETFL, 0);
     260         [ +  - ]:        196 :         if (ret < 0)
     261                 :            :                 goto err;
     262                 :            : 
     263                 :        196 :         flags = (SETFL_MASK & flags) | (ret & ~SETFL_MASK);
     264                 :            : 
     265                 :        196 :         ret = fcntl(fd, F_SETFL, flags);
     266         [ -  + ]:        196 :         if (ret < 0)
     267                 :            :                 goto err;
     268                 :            :         return 0;
     269                 :            : 
     270                 :            : err:
     271                 :          0 :         pr_perror("fcntl call on fd %d (flags %x) failed", fd, flags);
     272                 :        196 :         return -1;
     273                 :            : }
     274                 :            : 
     275                 :       1052 : static void transport_name_gen(struct sockaddr_un *addr, int *len,
     276                 :            :                 int pid, int fd)
     277                 :            : {
     278                 :       1052 :         addr->sun_family = AF_UNIX;
     279                 :       1052 :         snprintf(addr->sun_path, UNIX_PATH_MAX, "x/crtools-fd-%d-%d", pid, fd);
     280                 :       1052 :         *len = SUN_LEN(addr);
     281                 :       1052 :         *addr->sun_path = '\0';
     282                 :       1052 : }
     283                 :            : 
     284                 :            : static int should_open_transport(FdinfoEntry *fe, struct file_desc *fd)
     285                 :            : {
     286         [ +  + ]:        820 :         if (fd->ops->want_transport)
     287                 :        202 :                 return fd->ops->want_transport(fe, fd);
     288                 :            :         else
     289                 :            :                 return 0;
     290                 :            : }
     291                 :            : 
     292                 :       1512 : static int open_transport_fd(int pid, struct fdinfo_list_entry *fle)
     293                 :            : {
     294                 :            :         struct fdinfo_list_entry *flem;
     295                 :            :         struct sockaddr_un saddr;
     296                 :            :         int sock;
     297                 :            :         int ret, sun_len;
     298                 :            : 
     299                 :       1512 :         flem = file_master(fle->desc);
     300                 :            : 
     301         [ +  + ]:       1512 :         if (flem->pid == pid) {
     302         [ +  + ]:       1075 :                 if (flem->fe->fd != fle->fe->fd)
     303                 :            :                         /* dup-ed file. Will be opened in the open_fd */
     304                 :            :                         return 0;
     305                 :            : 
     306         [ +  + ]:        820 :                 if (!should_open_transport(fle->fe, fle->desc))
     307                 :            :                         /* pure master file */
     308                 :            :                         return 0;
     309                 :            : 
     310                 :            :                 /*
     311                 :            :                  * some master file, that wants a transport, e.g.
     312                 :            :                  * a pipe or unix socket pair 'slave' end
     313                 :            :                  */
     314                 :            :         }
     315                 :            : 
     316                 :        526 :         transport_name_gen(&saddr, &sun_len, getpid(), fle->fe->fd);
     317                 :            : 
     318                 :        526 :         pr_info("\t\tCreate transport fd %s\n", saddr.sun_path + 1);
     319                 :            : 
     320                 :            : 
     321                 :        526 :         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
     322         [ -  + ]:        526 :         if (sock < 0) {
     323                 :          0 :                 pr_perror("Can't create socket");
     324                 :            :                 return -1;
     325                 :            :         }
     326                 :        526 :         ret = bind(sock, &saddr, sun_len);
     327         [ -  + ]:        526 :         if (ret < 0) {
     328                 :          0 :                 pr_perror("Can't bind unix socket %s", saddr.sun_path + 1);
     329                 :            :                 return -1;
     330                 :            :         }
     331                 :            : 
     332                 :        526 :         ret = reopen_fd_as(fle->fe->fd, sock);
     333         [ +  - ]:        526 :         if (ret < 0)
     334                 :            :                 return -1;
     335                 :            : 
     336                 :        526 :         pr_info("\t\tWake up fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
     337                 :       1512 :         futex_set_and_wake(&fle->real_pid, getpid());
     338                 :            : 
     339                 :            :         return 0;
     340                 :            : }
     341                 :            : 
     342                 :        526 : int send_fd_to_peer(int fd, struct fdinfo_list_entry *fle, int sock)
     343                 :            : {
     344                 :            :         struct sockaddr_un saddr;
     345                 :            :         int len;
     346                 :            : 
     347                 :        526 :         pr_info("\t\tWait fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
     348                 :        526 :         futex_wait_while(&fle->real_pid, 0);
     349                 :        526 :         transport_name_gen(&saddr, &len,
     350                 :       1052 :                         futex_get(&fle->real_pid), fle->fe->fd);
     351                 :        526 :         pr_info("\t\tSend fd %d to %s\n", fd, saddr.sun_path + 1);
     352                 :        526 :         return send_fd(sock, &saddr, len, fd);
     353                 :            : }
     354                 :            : 
     355                 :       1075 : static int send_fd_to_self(int fd, struct fdinfo_list_entry *fle, int *sock)
     356                 :            : {
     357                 :       1075 :         int dfd = fle->fe->fd;
     358                 :            : 
     359         [ +  + ]:       1075 :         if (fd == dfd)
     360                 :            :                 return 0;
     361                 :            : 
     362                 :        255 :         pr_info("\t\t\tGoing to dup %d into %d\n", fd, dfd);
     363         [ +  - ]:        255 :         if (move_img_fd(sock, dfd))
     364                 :            :                 return -1;
     365                 :            : 
     366         [ -  + ]:        255 :         if (dup2(fd, dfd) != dfd) {
     367                 :          0 :                 pr_perror("Can't dup local fd %d -> %d", fd, dfd);
     368                 :            :                 return -1;
     369                 :            :         }
     370                 :            : 
     371                 :       1075 :         fcntl(dfd, F_SETFD, fle->fe->flags);
     372                 :            :         return 0;
     373                 :            : }
     374                 :            : 
     375                 :       1512 : static int post_open_fd(int pid, struct fdinfo_list_entry *fle)
     376                 :            : {
     377                 :       1512 :         struct file_desc *d = fle->desc;
     378                 :            : 
     379         [ +  + ]:       1512 :         if (!d->ops->post_open)
     380                 :            :                 return 0;
     381                 :            : 
     382         [ +  + ]:        123 :         if (is_service_fd(fle->fe->fd, CTL_TTY_OFF))
     383                 :          7 :                 return d->ops->post_open(d, fle->fe->fd);
     384                 :            : 
     385         [ +  - ]:        116 :         if (fle != file_master(d))
     386                 :            :                 return 0;
     387                 :            : 
     388                 :       1512 :         return d->ops->post_open(d, fle->fe->fd);
     389                 :            : }
     390                 :            : 
     391                 :            : 
     392                 :        820 : static int serve_out_fd(int pid, int fd, struct file_desc *d)
     393                 :            : {
     394                 :            :         int sock, ret;
     395                 :            :         struct fdinfo_list_entry *fle;
     396                 :            : 
     397                 :        820 :         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
     398         [ -  + ]:        820 :         if (sock < 0) {
     399                 :          0 :                 pr_perror("Can't create socket");
     400                 :            :                 return -1;
     401                 :            :         }
     402                 :            : 
     403                 :        820 :         pr_info("\t\tCreate fd for %d\n", fd);
     404                 :            : 
     405         [ +  + ]:       2332 :         list_for_each_entry(fle, &d->fd_info_head, desc_list) {
     406         [ +  + ]:       1512 :                 if (pid == fle->pid)
     407                 :       1075 :                         ret = send_fd_to_self(fd, fle, &sock);
     408                 :            :                 else
     409                 :        437 :                         ret = send_fd_to_peer(fd, fle, sock);
     410                 :            : 
     411         [ -  + ]:       1512 :                 if (ret) {
     412                 :          0 :                         pr_err("Can't sent fd %d to %d\n", fd, fle->pid);
     413                 :            :                         return -1;
     414                 :            :                 }
     415                 :            :         }
     416                 :            : 
     417                 :        820 :         close(sock);
     418                 :            :         return 0;
     419                 :            : }
     420                 :            : 
     421                 :       1512 : static int open_fd(int pid, struct fdinfo_list_entry *fle)
     422                 :            : {
     423                 :       1512 :         struct file_desc *d = fle->desc;
     424                 :            :         int new_fd;
     425                 :            : 
     426         [ +  + ]:       1512 :         if (fle != file_master(d))
     427                 :            :                 return 0;
     428                 :            : 
     429                 :        820 :         new_fd = d->ops->open(d);
     430         [ +  - ]:        820 :         if (new_fd < 0)
     431                 :            :                 return -1;
     432                 :            : 
     433         [ +  - ]:        820 :         if (reopen_fd_as(fle->fe->fd, new_fd))
     434                 :            :                 return -1;
     435                 :            : 
     436                 :        820 :         fcntl(fle->fe->fd, F_SETFD, fle->fe->flags);
     437                 :            : 
     438                 :       1512 :         return serve_out_fd(pid, fle->fe->fd, d);
     439                 :            : }
     440                 :            : 
     441                 :       1512 : static int receive_fd(int pid, struct fdinfo_list_entry *fle)
     442                 :            : {
     443                 :            :         int tmp;
     444                 :            :         struct fdinfo_list_entry *flem;
     445                 :            : 
     446                 :       1512 :         flem = file_master(fle->desc);
     447         [ +  + ]:       1512 :         if (flem->pid == pid)
     448                 :            :                 return 0;
     449                 :            : 
     450                 :        437 :         pr_info("\tReceive fd for %d\n", fle->fe->fd);
     451                 :            : 
     452                 :        437 :         tmp = recv_fd(fle->fe->fd);
     453         [ -  + ]:        437 :         if (tmp < 0) {
     454                 :          0 :                 pr_err("Can't get fd %d\n", tmp);
     455                 :          0 :                 return -1;
     456                 :            :         }
     457                 :        437 :         close(fle->fe->fd);
     458                 :            : 
     459         [ +  - ]:        437 :         if (reopen_fd_as(fle->fe->fd, tmp) < 0)
     460                 :            :                 return -1;
     461                 :            : 
     462                 :        437 :         fcntl(tmp, F_SETFD, fle->fe->flags);
     463                 :       1512 :         return 0;
     464                 :            : }
     465                 :            : 
     466                 :            : struct fd_open_state {
     467                 :            :         char *name;
     468                 :            :         int (*cb)(int, struct fdinfo_list_entry *);
     469                 :            : };
     470                 :            : 
     471                 :            : static struct fd_open_state states[] = {
     472                 :            :         { "prepare",          open_transport_fd, },
     473                 :            :         { "create",           open_fd, },
     474                 :            :         { "receive",          receive_fd, },
     475                 :            :         { "post_create",      post_open_fd, },
     476                 :            : };
     477                 :            : 
     478                 :       6048 : static int open_fdinfo(int pid, struct fdinfo_list_entry *fle, int state)
     479                 :            : {
     480                 :       6048 :         pr_info("\tRestoring fd %d (state -> %s)\n",
     481                 :            :                         fle->fe->fd, states[state].name);
     482                 :       6048 :         return states[state].cb(pid, fle);
     483                 :            : }
     484                 :            : 
     485                 :       4188 : static int open_fdinfos(int pid, struct list_head *list, int state)
     486                 :            : {
     487                 :       4188 :         int ret = 0;
     488                 :            :         struct fdinfo_list_entry *fle;
     489                 :            : 
     490         [ +  + ]:      10236 :         list_for_each_entry(fle, list, ps_list) {
     491                 :       6048 :                 ret = open_fdinfo(pid, fle, state);
     492         [ +  - ]:       6048 :                 if (ret)
     493                 :            :                         break;
     494                 :            :         }
     495                 :            : 
     496                 :       4188 :         return ret;
     497                 :            : }
     498                 :            : 
     499                 :        349 : static int close_old_fds(struct pstree_item *me)
     500                 :            : {
     501                 :            :         DIR *dir;
     502                 :            :         struct dirent *de;
     503                 :            :         int fd, ret;
     504                 :            : 
     505 [ -  + ][ +  - ]:        349 :         dir = opendir_proc(getpid(), "fd");
                 [ -  + ]
     506         [ +  - ]:        349 :         if (dir == NULL)
     507                 :            :                 return -1;
     508                 :            : 
     509         [ +  + ]:       4537 :         while ((de = readdir(dir))) {
     510         [ +  + ]:       4188 :                 if (dir_dots(de))
     511                 :        698 :                         continue;
     512                 :            : 
     513                 :       3490 :                 ret = sscanf(de->d_name, "%d", &fd);
     514         [ -  + ]:       3490 :                 if (ret != 1) {
     515                 :          0 :                         pr_err("Can't parse %s\n", de->d_name);
     516                 :            :                         return -1;
     517                 :            :                 }
     518                 :            : 
     519 [ +  + ][ +  + ]:       3490 :                 if ((!is_any_service_fd(fd)) && (dirfd(dir) != fd))
     520                 :       4188 :                         close_safe(&fd);
     521                 :            :         }
     522                 :            : 
     523                 :        349 :         closedir(dir);
     524                 :        349 :         close_pid_proc();
     525                 :            : 
     526                 :            :         return 0;
     527                 :            : }
     528                 :            : 
     529                 :        349 : int prepare_fds(struct pstree_item *me)
     530                 :            : {
     531                 :            :         u32 ret;
     532                 :            :         int state;
     533                 :            : 
     534                 :        349 :         ret = close_old_fds(me);
     535         [ +  - ]:        349 :         if (ret)
     536                 :            :                 goto err;
     537                 :            : 
     538                 :        349 :         pr_info("Opening fdinfo-s\n");
     539                 :            : 
     540         [ +  + ]:       1745 :         for (state = 0; state < ARRAY_SIZE(states); state++) {
     541                 :       1396 :                 ret = open_fdinfos(me->pid.virt, &me->rst->fds, state);
     542         [ +  - ]:       1396 :                 if (ret)
     543                 :            :                         break;
     544                 :            : 
     545                 :            :                 /*
     546                 :            :                  * Now handle TTYs. Slaves are delayed to be sure masters
     547                 :            :                  * are already opened.
     548                 :            :                  */
     549                 :       1396 :                 ret = open_fdinfos(me->pid.virt, &me->rst->tty_slaves, state);
     550         [ +  - ]:       1396 :                 if (ret)
     551                 :            :                         break;
     552                 :            : 
     553                 :            :                 /*
     554                 :            :                  * The eventpoll descriptors require all the other ones
     555                 :            :                  * to be already restored, thus we store them in a separate
     556                 :            :                  * list and restore at the very end.
     557                 :            :                  */
     558                 :       1396 :                 ret = open_fdinfos(me->pid.virt, &me->rst->eventpoll, state);
     559         [ +  - ]:       1396 :                 if (ret)
     560                 :            :                         break;
     561                 :            :         }
     562                 :            : 
     563                 :            : err:
     564                 :        349 :         tty_fini_fds();
     565                 :        349 :         return ret;
     566                 :            : }
     567                 :            : 
     568                 :        349 : int prepare_fs(int pid)
     569                 :            : {
     570                 :        349 :         int ifd, cwd, ret = -1;
     571                 :            :         FsEntry *fe;
     572                 :            : 
     573                 :        349 :         ifd = open_image_ro(CR_FD_FS, pid);
     574         [ +  - ]:        349 :         if (ifd < 0)
     575                 :            :                 return -1;
     576                 :            : 
     577         [ -  + ]:        349 :         if (pb_read_one(ifd, &fe, PB_FS) < 0) {
     578                 :          0 :                 close_safe(&ifd);
     579                 :            :                 return -1;
     580                 :            :         }
     581                 :            : 
     582                 :        349 :         cwd = open_reg_by_id(fe->cwd_id);
     583         [ -  + ]:        349 :         if (cwd < 0) {
     584                 :          0 :                 close_safe(&ifd);
     585                 :          0 :                 goto err;
     586                 :            :         }
     587                 :            : 
     588         [ -  + ]:        349 :         if (fchdir(cwd) < 0) {
     589                 :          0 :                 pr_perror("Can't change root");
     590                 :          0 :                 goto close;
     591                 :            :         }
     592                 :            : 
     593                 :            :         /*
     594                 :            :          * FIXME: restore task's root. Don't want to do it now, since
     595                 :            :          * it's not yet clean how we're going to resolve tasks' paths
     596                 :            :          * relative to the dumper/restorer and all this logic is likely
     597                 :            :          * to be hidden in a couple of calls (open_fe_fd is one od them)
     598                 :            :          * but for chroot there's no fchroot call, we have to chroot
     599                 :            :          * by path thus exposing this (yet unclean) logic here.
     600                 :            :          */
     601                 :            : 
     602                 :            :         ret = 0;
     603                 :            : close:
     604                 :        349 :         close_safe(&cwd);
     605                 :        349 :         close_safe(&ifd);
     606                 :            : err:
     607                 :        349 :         fs_entry__free_unpacked(fe, NULL);
     608                 :            :         return ret;
     609                 :            : }
     610                 :            : 
     611                 :       5724 : int get_filemap_fd(int pid, VmaEntry *vma_entry)
     612                 :            : {
     613                 :       5724 :         return open_reg_by_id(vma_entry->shmid);
     614                 :      12871 : }

Generated by: LCOV version 1.9