LCOV - code coverage report
Current view: top level - home/snorch/criu - sk-unix.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 330 422 78.2 %
Date: 2014-04-22 Functions: 20 20 100.0 %
Branches: 203 316 64.2 %

           Branch data     Line data    Source code
       1                 :            : #include <sys/socket.h>
       2                 :            : #include <linux/netlink.h>
       3                 :            : #include <linux/rtnetlink.h>
       4                 :            : #include <unistd.h>
       5                 :            : #include <netinet/tcp.h>
       6                 :            : #include <sys/stat.h>
       7                 :            : #include <fcntl.h>
       8                 :            : #include <sys/un.h>
       9                 :            : #include <stdlib.h>
      10                 :            : #include <dlfcn.h>
      11                 :            : 
      12                 :            : #include "asm/types.h"
      13                 :            : #include "libnetlink.h"
      14                 :            : #include "cr_options.h"
      15                 :            : #include "fdset.h"
      16                 :            : #include "unix_diag.h"
      17                 :            : #include "files.h"
      18                 :            : #include "file-ids.h"
      19                 :            : #include "image.h"
      20                 :            : #include "log.h"
      21                 :            : #include "util.h"
      22                 :            : #include "util-pie.h"
      23                 :            : #include "sockets.h"
      24                 :            : #include "sk-queue.h"
      25                 :            : #include "mount.h"
      26                 :            : #include "cr-service.h"
      27                 :            : #include "plugin.h"
      28                 :            : #include "namespaces.h"
      29                 :            : #include "pstree.h"
      30                 :            : 
      31                 :            : #include "protobuf.h"
      32                 :            : #include "protobuf/sk-unix.pb-c.h"
      33                 :            : 
      34                 :            : struct unix_sk_desc {
      35                 :            :         struct socket_desc      sd;
      36                 :            :         unsigned int            type;
      37                 :            :         unsigned int            state;
      38                 :            :         unsigned int            peer_ino;
      39                 :            :         unsigned int            rqlen;
      40                 :            :         unsigned int            wqlen;
      41                 :            :         unsigned int            namelen;
      42                 :            :         char                    *name;
      43                 :            :         unsigned int            nr_icons;
      44                 :            :         unsigned int            *icons;
      45                 :            :         unsigned char           shutdown;
      46                 :            : 
      47                 :            :         mode_t                  mode;
      48                 :            :         uid_t                   uid;
      49                 :            :         gid_t                   gid;
      50                 :            : 
      51                 :            :         struct list_head        list;
      52                 :            : 
      53                 :            :         int                     fd;
      54                 :            :         struct list_head        peer_list;
      55                 :            :         struct list_head        peer_node;
      56                 :            : 
      57                 :            :         UnixSkEntry             *ue;
      58                 :            : };
      59                 :            : 
      60                 :            : static LIST_HEAD(unix_sockets);
      61                 :            : 
      62                 :            : struct unix_sk_listen_icon {
      63                 :            :         unsigned int                    peer_ino;
      64                 :            :         struct unix_sk_desc             *sk_desc;
      65                 :            :         struct unix_sk_listen_icon      *next;
      66                 :            : };
      67                 :            : 
      68                 :            : #define SK_HASH_SIZE            32
      69                 :            : 
      70                 :            : static struct unix_sk_listen_icon *unix_listen_icons[SK_HASH_SIZE];
      71                 :            : 
      72                 :            : static struct unix_sk_listen_icon *lookup_unix_listen_icons(int peer_ino)
      73                 :            : {
      74                 :            :         struct unix_sk_listen_icon *ic;
      75                 :            : 
      76         [ +  + ]:          8 :         for (ic = unix_listen_icons[peer_ino % SK_HASH_SIZE];
      77                 :          0 :                         ic; ic = ic->next)
      78         [ -  + ]:          4 :                 if (ic->peer_ino == peer_ino)
      79                 :            :                         return ic;
      80                 :            :         return NULL;
      81                 :            : }
      82                 :            : 
      83                 :     133684 : static void show_one_unix(char *act, const struct unix_sk_desc *sk)
      84                 :            : {
      85                 :     133684 :         pr_debug("\t%s: ino %#x peer_ino %#x family %4d type %4d state %2d name %s\n",
      86                 :            :                 act, sk->sd.ino, sk->peer_ino, sk->sd.family, sk->type, sk->state, sk->name);
      87                 :            : 
      88         [ +  + ]:     133684 :         if (sk->nr_icons) {
      89                 :            :                 int i;
      90                 :            : 
      91         [ +  + ]:         16 :                 for (i = 0; i < sk->nr_icons; i++)
      92                 :          8 :                         pr_debug("\t\ticon: %4d\n", sk->icons[i]);
      93                 :            :         }
      94                 :     133684 : }
      95                 :            : 
      96                 :        120 : static void show_one_unix_img(const char *act, const UnixSkEntry *e)
      97                 :            : {
      98                 :        120 :         pr_info("\t%s: id %#x ino %#x peer %#x type %d state %d name %d bytes\n",
      99                 :            :                 act, e->id, e->ino, e->peer, e->type, e->state, (int)e->name.len);
     100                 :        120 : }
     101                 :            : 
     102                 :        236 : static int can_dump_unix_sk(const struct unix_sk_desc *sk)
     103                 :            : {
     104                 :            :         /*
     105                 :            :          * The last case in this "if" is seqpacket socket,
     106                 :            :          * that is connected to cr_service. We will dump
     107                 :            :          * it properly below.
     108                 :            :          */
     109         [ -  + ]:        118 :         if (sk->type != SOCK_STREAM &&
     110                 :        118 :             sk->type != SOCK_DGRAM &&
     111                 :            :             sk->type != SOCK_SEQPACKET) {
     112                 :          0 :                 pr_err("Unsupported type (%d) on socket %x.\n"
     113                 :            :                                 "Only stream/dgram/seqpacket are supported.\n",
     114                 :            :                                 sk->type, sk->sd.ino);
     115                 :            :                 return 0;
     116                 :            :         }
     117                 :            : 
     118 [ +  - ][ -  + ]:        118 :         switch (sk->state) {
     119                 :            :         case TCP_LISTEN:
     120                 :            :         case TCP_ESTABLISHED:
     121                 :            :         case TCP_CLOSE:
     122                 :            :                 break;
     123                 :            :         default:
     124                 :          0 :                 pr_err("Unknown state %d for unix socket %x\n",
     125                 :            :                                 sk->state, sk->sd.ino);
     126                 :            :                 return 0;
     127                 :            :         }
     128                 :            : 
     129                 :            :         return 1;
     130                 :            : }
     131                 :            : 
     132                 :        236 : static int write_unix_entry(struct unix_sk_desc *sk)
     133                 :            : {
     134                 :            :         int ret;
     135                 :            : 
     136                 :        118 :         ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), sk->ue, PB_UNIX_SK);
     137                 :            : 
     138                 :        118 :         show_one_unix_img("Dumped", sk->ue);
     139                 :            : 
     140                 :        118 :         release_skopts(sk->ue->opts);
     141         [ +  - ]:        118 :         xfree(sk->ue);
     142                 :            : 
     143                 :        118 :         sk->ue = NULL;
     144                 :            : 
     145                 :        118 :         return ret;
     146                 :            : }
     147                 :            : 
     148                 :        118 : static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
     149                 :            : {
     150                 :        118 :         struct unix_sk_desc *sk, *peer;
     151                 :            :         UnixSkEntry *ue;
     152                 :            :         SkOptsEntry *skopts;
     153                 :            :         FilePermsEntry *perms;
     154                 :            :         FownEntry *fown;
     155                 :            : 
     156         [ -  + ]:        118 :         ue = xmalloc(sizeof(UnixSkEntry) +
     157                 :            :                         sizeof(SkOptsEntry) +
     158                 :            :                         sizeof(FilePermsEntry) +
     159                 :            :                         sizeof(FownEntry));
     160         [ +  - ]:        118 :         if (ue == NULL)
     161                 :            :                 return -1;
     162                 :            : 
     163                 :        118 :         skopts = (void *) ue + sizeof(UnixSkEntry);
     164                 :        118 :         perms = (void *) skopts + sizeof(SkOptsEntry);
     165                 :        118 :         fown = (void *) perms + sizeof(FilePermsEntry);
     166                 :            : 
     167                 :        118 :         unix_sk_entry__init(ue);
     168                 :        118 :         sk_opts_entry__init(skopts);
     169                 :        118 :         file_perms_entry__init(perms);
     170                 :            : 
     171                 :        118 :         *fown = p->fown;
     172                 :            : 
     173                 :        118 :         sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino, PF_UNIX, 0);
     174         [ -  + ]:        118 :         if (IS_ERR_OR_NULL(sk)) {
     175                 :          0 :                 pr_err("Unix socket %#x not found\n", (int)p->stat.st_ino);
     176                 :          0 :                 goto err;
     177                 :            :         }
     178                 :            : 
     179         [ +  - ]:        118 :         if (!can_dump_unix_sk(sk))
     180                 :            :                 goto err;
     181                 :            : 
     182         [ -  + ]:        118 :         BUG_ON(sk->sd.already_dumped);
     183                 :            : 
     184                 :        118 :         ue->name.len = (size_t)sk->namelen;
     185                 :        118 :         ue->name.data        = (void *)sk->name;
     186                 :            : 
     187                 :        118 :         ue->id               = id;
     188                 :        118 :         ue->ino              = sk->sd.ino;
     189                 :        118 :         ue->type     = sk->type;
     190                 :        118 :         ue->state    = sk->state;
     191                 :        118 :         ue->flags    = p->flags;
     192                 :        118 :         ue->backlog  = sk->wqlen;
     193                 :        118 :         ue->peer     = sk->peer_ino;
     194                 :        118 :         ue->fown     = fown;
     195                 :        118 :         ue->opts     = skopts;
     196                 :        118 :         ue->uflags   = 0;
     197                 :            : 
     198                 :            :         /*
     199                 :            :          * Check if this socket is connected to criu service.
     200                 :            :          * Dump it like closed one and mark it for restore.
     201                 :            :          */
     202         [ -  + ]:        118 :         if (unlikely(ue->peer == service_sk_ino)) {
     203                 :          0 :                 ue->state = TCP_CLOSE;
     204                 :          0 :                 ue->peer = 0;
     205                 :          0 :                 ue->uflags |= USK_SERVICE;
     206                 :            :         }
     207                 :            : 
     208 [ +  + ][ +  + ]:        118 :         if (sk->namelen && *sk->name) {
     209                 :         20 :                 ue->file_perms = perms;
     210                 :            : 
     211                 :         20 :                 perms->mode  = sk->mode;
     212                 :         20 :                 perms->uid   = sk->uid;
     213                 :         20 :                 perms->gid   = sk->gid;
     214                 :            :         }
     215                 :            : 
     216         [ +  + ]:        118 :         sk_encode_shutdown(ue, sk->shutdown);
     217                 :            : 
     218         [ +  + ]:        118 :         if (ue->peer) {
     219                 :         86 :                 peer = (struct unix_sk_desc *)lookup_socket(ue->peer, PF_UNIX, 0);
     220         [ -  + ]:         86 :                 if (IS_ERR_OR_NULL(peer)) {
     221                 :          0 :                         pr_err("Unix socket %#x without peer %#x\n",
     222                 :            :                                         ue->ino, ue->peer);
     223                 :          0 :                         goto err;
     224                 :            :                 }
     225                 :            : 
     226                 :            :                 /*
     227                 :            :                  * Peer should have us as peer or have a name by which
     228                 :            :                  * we can access one.
     229                 :            :                  */
     230         [ +  + ]:         86 :                 if (peer->peer_ino != ue->ino) {
     231         [ -  + ]:         10 :                         if (!peer->name) {
     232                 :          0 :                                 pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
     233                 :            :                                        ue->ino, ue->peer, peer->peer_ino, peer->name);
     234                 :          0 :                                 goto err;
     235                 :            :                         }
     236                 :            :                 }
     237                 :            : 
     238                 :            :                 /*
     239                 :            :                  * It can be external socket, so we defer dumping
     240                 :            :                  * until all sockets the program owns are processed.
     241                 :            :                  */
     242         [ +  + ]:         86 :                 if (!peer->sd.already_dumped) {
     243         [ +  + ]:         50 :                         if (list_empty(&peer->list)) {
     244                 :         46 :                                 show_one_unix("Add a peer", peer);
     245                 :            :                                 list_add_tail(&peer->list, &unix_sockets);
     246                 :            :                         }
     247                 :            : 
     248                 :         50 :                         list_add(&sk->peer_node, &peer->peer_list);
     249                 :         50 :                         sk->fd = dup(lfd);
     250         [ -  + ]:         50 :                         if (sk->fd < 0) {
     251                 :          0 :                                 pr_perror("Unable to dup(%d)", lfd);
     252                 :          0 :                                 goto err;
     253                 :            :                         }
     254                 :            :                 }
     255                 :            : 
     256 [ +  + ][ +  + ]:         86 :                 if ((ue->type != SOCK_DGRAM) && (
     257         [ +  - ]:          4 :                                 ((ue->shutdown == SK_SHUTDOWN__READ)  &&
     258         [ +  + ]:         40 :                                  (peer->shutdown != SK_SHUTDOWN__WRITE)) ||
     259         [ +  - ]:          4 :                                 ((ue->shutdown == SK_SHUTDOWN__WRITE) &&
     260         [ +  + ]:         40 :                                  (peer->shutdown != SK_SHUTDOWN__READ))  ||
     261         [ -  + ]:          8 :                                 ((ue->shutdown == SK_SHUTDOWN__BOTH)  &&
     262                 :          8 :                                  (peer->shutdown != SK_SHUTDOWN__BOTH)) )) {
     263                 :            :                         /*
     264                 :            :                          * On restore we assume, that stream pairs must
     265                 :            :                          * be shut down from one end only
     266                 :            :                          */
     267                 :          0 :                         pr_err("Shutdown mismatch %u:%d -> %u:%d\n",
     268                 :            :                                         ue->ino, ue->shutdown, peer->sd.ino, peer->shutdown);
     269                 :          0 :                         goto err;
     270                 :            :                 }
     271         [ +  + ]:         32 :         } else if (ue->state == TCP_ESTABLISHED) {
     272                 :            :                 const struct unix_sk_listen_icon *e;
     273                 :            : 
     274                 :          8 :                 e = lookup_unix_listen_icons(ue->ino);
     275         [ +  + ]:          8 :                 if (!e) {
     276                 :            :                         /*
     277                 :            :                          * ESTABLISHED socket without peer and without
     278                 :            :                          * anyone waiting for it should be semi-closed
     279                 :            :                          * connection.
     280                 :            :                          */
     281                 :            : 
     282         [ +  - ]:          4 :                         if (ue->shutdown == SK_SHUTDOWN__BOTH) {
     283                 :          4 :                                 pr_info("Dumping semi-closed connection\n");
     284                 :          4 :                                 goto dump;
     285                 :            :                         }
     286                 :            : 
     287                 :          0 :                         pr_err("Dangling connection %#x\n", ue->ino);
     288                 :          0 :                         goto err;
     289                 :            :                 }
     290                 :            : 
     291                 :            :                 /*
     292                 :            :                  * If this is in-flight connection we need to figure
     293                 :            :                  * out where to connect it on restore. Thus, tune up peer
     294                 :            :                  * id by searching an existing listening socket.
     295                 :            :                  *
     296                 :            :                  * Note the socket name will be found at restore stage,
     297                 :            :                  * not now, just to reduce size of dump files.
     298                 :            :                  */
     299                 :            : 
     300                 :            :                 /* e->sk_desc is _never_ NULL */
     301         [ -  + ]:          4 :                 if (e->sk_desc->state != TCP_LISTEN) {
     302                 :          0 :                         pr_err("In-flight connection on "
     303                 :            :                                 "non-listening socket %d\n", ue->ino);
     304                 :          0 :                         goto err;
     305                 :            :                 }
     306                 :            : 
     307                 :          4 :                 ue->peer = e->sk_desc->sd.ino;
     308                 :            : 
     309                 :          4 :                 pr_debug("\t\tFixed inflight socket %#x peer %#x)\n",
     310                 :            :                                 ue->ino, ue->peer);
     311                 :            :         }
     312                 :            : dump:
     313         [ +  - ]:        118 :         if (dump_socket_opts(lfd, skopts))
     314                 :            :                 goto err;
     315                 :            : 
     316                 :            :         /*
     317                 :            :          * If a stream listening socket has non-zero rqueue, this
     318                 :            :          * means there are in-flight connections waiting to get
     319                 :            :          * accept()-ed. We handle them separately with the "icons"
     320                 :            :          * (i stands for in-flight, cons -- for connections) things.
     321                 :            :          */
     322 [ +  + ][ +  + ]:        118 :         if (sk->rqlen != 0 && !(sk->type == SOCK_STREAM &&
     323                 :            :                                 sk->state == TCP_LISTEN))
     324         [ +  - ]:         24 :                 if (dump_sk_queue(lfd, id))
     325                 :            :                         goto err;
     326                 :            : 
     327                 :        118 :         pr_info("Dumping unix socket at %d\n", p->fd);
     328                 :        118 :         show_one_unix("Dumping", sk);
     329                 :            : 
     330                 :        118 :         sk->ue = ue;
     331                 :            :         /*
     332                 :            :          *  Postpone writing the entry if a peer isn't found yet.
     333                 :            :          *  It's required, because we may need to modify the entry.
     334                 :            :          *  For example, if a socket is external and is dumped by
     335                 :            :          *  a callback, the USK_CALLBACK flag must be set.
     336                 :            :          */
     337 [ +  + ][ +  - ]:        118 :         if (list_empty(&sk->peer_node) && write_unix_entry(sk))
     338                 :            :                 return -1;
     339                 :            : 
     340                 :        118 :         list_del_init(&sk->list);
     341                 :        118 :         sk->sd.already_dumped = 1;
     342                 :            : 
     343         [ +  + ]:        166 :         while (!list_empty(&sk->peer_list)) {
     344                 :            :                 struct unix_sk_desc *psk;
     345                 :            :                 psk = list_first_entry(&sk->peer_list, struct unix_sk_desc, peer_node);
     346                 :         48 :                 close_safe(&psk->fd);
     347                 :         48 :                 list_del_init(&psk->peer_node);
     348                 :            : 
     349         [ +  - ]:         48 :                 if (write_unix_entry(psk))
     350                 :            :                         return -1;
     351                 :            :         }
     352                 :            : 
     353                 :            :         return 0;
     354                 :            : 
     355                 :            : err:
     356                 :          0 :         release_skopts(skopts);
     357         [ #  # ]:          0 :         xfree(ue);
     358                 :            :         return -1;
     359                 :            : }
     360                 :            : 
     361                 :            : const struct fdtype_ops unix_dump_ops = {
     362                 :            :         .type           = FD_TYPES__UNIXSK,
     363                 :            :         .dump           = dump_one_unix_fd,
     364                 :            : };
     365                 :            : 
     366                 :     133518 : static int unix_collect_one(const struct unix_diag_msg *m,
     367                 :            :                 struct rtattr **tb)
     368                 :            : {
     369                 :            :         struct unix_sk_desc *d;
     370                 :            :         char *name = NULL;
     371                 :            :         struct ns_id *ns;
     372                 :            :         int ret = 0;
     373                 :            : 
     374                 :     133518 :         ns = lookup_ns_by_id(root_item->ids->mnt_ns_id, &mnt_ns_desc);
     375         [ +  - ]:     133518 :         if (ns == NULL)
     376                 :            :                 return -1;
     377                 :            : 
     378         [ +  - ]:     133518 :         if (mntns_collect_root(ns->pid) < 0)
     379                 :            :                 return -1;
     380                 :            : 
     381         [ -  + ]:     133518 :         d = xzalloc(sizeof(*d));
     382         [ +  - ]:     133518 :         if (!d)
     383                 :            :                 return -1;
     384                 :            : 
     385                 :     133518 :         d->type       = m->udiag_type;
     386                 :     133518 :         d->state = m->udiag_state;
     387                 :     133518 :         INIT_LIST_HEAD(&d->list);
     388                 :            : 
     389                 :     133518 :         INIT_LIST_HEAD(&d->peer_list);
     390                 :     133518 :         INIT_LIST_HEAD(&d->peer_node);
     391                 :     133518 :         d->fd = -1;
     392                 :            : 
     393         [ +  - ]:     133518 :         if (tb[UNIX_DIAG_SHUTDOWN])
     394                 :     133518 :                 d->shutdown = *(u8 *)RTA_DATA(tb[UNIX_DIAG_SHUTDOWN]);
     395                 :            :         else
     396         [ #  # ]:          0 :                 pr_err_once("No socket shutdown info\n");
     397                 :            : 
     398         [ +  + ]:     133518 :         if (tb[UNIX_DIAG_PEER])
     399                 :     125704 :                 d->peer_ino = *(int *)RTA_DATA(tb[UNIX_DIAG_PEER]);
     400                 :            : 
     401         [ +  + ]:     133518 :         if (tb[UNIX_DIAG_NAME]) {
     402                 :      53993 :                 int len         = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
     403                 :            : 
     404         [ -  + ]:      53993 :                 name = xmalloc(len + 1);
     405         [ +  - ]:      53993 :                 if (!name)
     406                 :            :                         goto err;
     407                 :            : 
     408                 :      53993 :                 memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
     409                 :      53993 :                 name[len] = '\0';
     410                 :            : 
     411         [ +  + ]:      53993 :                 if (name[0] != '\0') {
     412                 :            :                         struct unix_diag_vfs *uv;
     413                 :            :                         struct stat st;
     414                 :            :                         char rpath[PATH_MAX];
     415                 :            :                         bool drop_path = false;
     416                 :            :                         int mntns_root;
     417                 :            : 
     418         [ -  + ]:      18825 :                         if (name[0] != '/') {
     419                 :          0 :                                 pr_warn("Relative bind path '%s' "
     420                 :            :                                         "unsupported\n", name);
     421                 :          0 :                                 goto skip;
     422                 :            :                         }
     423                 :            : 
     424         [ -  + ]:      18825 :                         if (!tb[UNIX_DIAG_VFS]) {
     425                 :          0 :                                 pr_err("Bound socket w/o inode %#x\n",
     426                 :            :                                                 m->udiag_ino);
     427                 :          0 :                                 goto skip;
     428                 :            :                         }
     429                 :            : 
     430                 :      18825 :                         mntns_root = get_service_fd(ROOT_FD_OFF);
     431                 :            : 
     432                 :      18825 :                         uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
     433                 :            :                         snprintf(rpath, sizeof(rpath), ".%s", name);
     434         [ -  + ]:      18825 :                         if (fstatat(mntns_root, rpath, &st, 0)) {
     435         [ #  # ]:          0 :                                 if (errno != ENOENT) {
     436                 :          0 :                                         pr_warn("Can't stat socket %#x(%s), skipping: %m (err %d)\n",
     437                 :            :                                                         m->udiag_ino, rpath, errno);
     438                 :          0 :                                         goto skip;
     439                 :            :                                 }
     440                 :            : 
     441                 :          0 :                                 pr_info("unix: Dropping path %s for unlinked sk %#x\n",
     442                 :            :                                                 name, m->udiag_ino);
     443                 :            :                                 drop_path = true;
     444   [ +  -  -  + ]:      37650 :                         } else if ((st.st_ino != uv->udiag_vfs_ino) ||
     445                 :      18825 :                             !phys_stat_dev_match(ns->mnt.mntinfo_tree, st.st_dev,
     446                 :      18825 :                                                         uv->udiag_vfs_dev, name)) {
     447                 :          0 :                                 pr_info("unix: Dropping path %s for "
     448                 :            :                                                 "unlinked bound "
     449                 :            :                                                 "sk %#x.%#x real %#x.%#x\n",
     450                 :            :                                                 name,
     451                 :            :                                                 (int)st.st_dev,
     452                 :            :                                                 (int)st.st_ino,
     453                 :            :                                                 (int)uv->udiag_vfs_dev,
     454                 :            :                                                 (int)uv->udiag_vfs_ino);
     455                 :            :                                 drop_path = true;
     456                 :            :                         }
     457                 :            : 
     458         [ -  + ]:      18825 :                         if (drop_path) {
     459                 :            :                                 /*
     460                 :            :                                  * When a socket is bound to unlinked file, we
     461                 :            :                                  * just drop his name, since no one will access
     462                 :            :                                  * it via one.
     463                 :            :                                  */
     464         [ #  # ]:          0 :                                 xfree(name);
     465                 :            :                                 len = 0;
     466                 :            :                                 name = NULL;
     467                 :            :                         }
     468                 :            : 
     469                 :      18825 :                         d->mode = st.st_mode;
     470                 :      18825 :                         d->uid       = st.st_uid;
     471                 :      18825 :                         d->gid       = st.st_gid;
     472                 :            :                 }
     473                 :            : 
     474                 :      53993 :                 d->namelen = len;
     475                 :      53993 :                 d->name = name;
     476                 :            :         }
     477                 :            : 
     478         [ +  + ]:     133518 :         if (tb[UNIX_DIAG_ICONS]) {
     479                 :       6848 :                 int len = RTA_PAYLOAD(tb[UNIX_DIAG_ICONS]);
     480                 :            :                 int i;
     481                 :            : 
     482         [ -  + ]:       6848 :                 d->icons = xmalloc(len);
     483         [ +  - ]:       6848 :                 if (!d->icons)
     484                 :            :                         goto err;
     485                 :            : 
     486                 :       6848 :                 memcpy(d->icons, RTA_DATA(tb[UNIX_DIAG_ICONS]), len);
     487                 :       6848 :                 d->nr_icons = len / sizeof(u32);
     488                 :            : 
     489                 :            :                 /*
     490                 :            :                  * Remember these sockets, we will need them
     491                 :            :                  * to fix up in-flight sockets peers.
     492                 :            :                  */
     493         [ +  + ]:       6852 :                 for (i = 0; i < d->nr_icons; i++) {
     494                 :            :                         struct unix_sk_listen_icon *e, **chain;
     495                 :            :                         int n;
     496                 :            : 
     497         [ -  + ]:          4 :                         e = xzalloc(sizeof(*e));
     498         [ +  - ]:          4 :                         if (!e)
     499                 :            :                                 goto err;
     500                 :            : 
     501                 :          4 :                         n = d->icons[i];
     502                 :          4 :                         chain = &unix_listen_icons[n % SK_HASH_SIZE];
     503                 :          4 :                         e->next = *chain;
     504                 :          4 :                         *chain = e;
     505                 :            : 
     506                 :          4 :                         pr_debug("\t\tCollected icon %d\n", d->icons[i]);
     507                 :            : 
     508                 :          4 :                         e->peer_ino  = n;
     509                 :          4 :                         e->sk_desc   = d;
     510                 :            :                 }
     511                 :            : 
     512                 :            : 
     513                 :            :         }
     514                 :            : 
     515         [ +  - ]:     133518 :         if (tb[UNIX_DIAG_RQLEN]) {
     516                 :            :                 struct unix_diag_rqlen *rq;
     517                 :            : 
     518                 :            :                 rq = (struct unix_diag_rqlen *)RTA_DATA(tb[UNIX_DIAG_RQLEN]);
     519                 :     133518 :                 d->rqlen = rq->udiag_rqueue;
     520                 :     133518 :                 d->wqlen = rq->udiag_wqueue;
     521                 :            :         }
     522                 :            : 
     523                 :     133518 :         sk_collect_one(m->udiag_ino, AF_UNIX, &d->sd);
     524                 :     133518 :         show_one_unix("Collected", d);
     525                 :            : 
     526                 :     133518 :         return 0;
     527                 :            : err:
     528                 :            :         ret = -1;
     529                 :            : skip:
     530         [ #  # ]:          0 :         xfree(d->icons);
     531         [ #  # ]:          0 :         xfree(name);
     532         [ #  # ]:          0 :         xfree(d);
     533                 :          0 :         return ret;
     534                 :            : }
     535                 :            : 
     536                 :     133518 : int unix_receive_one(struct nlmsghdr *h, void *arg)
     537                 :            : {
     538                 :     133518 :         struct unix_diag_msg *m = NLMSG_DATA(h);
     539                 :            :         struct rtattr *tb[UNIX_DIAG_MAX+1];
     540                 :            : 
     541                 :     133518 :         parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr *)(m + 1),
     542                 :     133518 :                      h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
     543                 :            : 
     544                 :     133518 :         return unix_collect_one(m, tb);
     545                 :            : }
     546                 :            : 
     547                 :          2 : static int dump_external_sockets(struct unix_sk_desc *peer)
     548                 :            : {
     549                 :            :         struct unix_sk_desc *sk;
     550                 :            :         int ret;
     551                 :            : 
     552         [ +  + ]:          4 :         while (!list_empty(&peer->peer_list)) {
     553                 :            :                 sk = list_first_entry(&peer->peer_list, struct unix_sk_desc, peer_node);
     554                 :            : 
     555                 :          2 :                 ret = cr_plugin_dump_unix_sk(sk->fd, sk->sd.ino);
     556         [ +  - ]:          2 :                 if (ret == -ENOTSUP) {
     557         [ -  + ]:          2 :                         if (!opts.ext_unix_sk) {
     558                 :          0 :                                 show_one_unix("Runaway socket", peer);
     559                 :          0 :                                 pr_err("External socket is used. "
     560                 :            :                                                 "Consider using --" USK_EXT_PARAM " option.\n");
     561                 :          0 :                                 return -1;
     562                 :            :                         }
     563                 :            : 
     564         [ -  + ]:          2 :                         if (peer->type != SOCK_DGRAM) {
     565                 :          0 :                                 show_one_unix("Ext stream not supported", peer);
     566                 :          0 :                                 pr_err("Can't dump half of stream unix connection.\n");
     567                 :          0 :                                 return -1;
     568                 :            :                         }
     569         [ #  # ]:          0 :                 } else if (ret < 0)
     570                 :            :                         return -1;
     571                 :            :                 else
     572                 :          0 :                         sk->ue->uflags |= USK_CALLBACK;
     573                 :            : 
     574         [ +  - ]:          2 :                 if (write_unix_entry(sk))
     575                 :            :                         return -1;
     576                 :          2 :                 close_safe(&sk->fd);
     577                 :          2 :                 list_del_init(&sk->peer_node);
     578                 :            :         }
     579                 :            : 
     580                 :            :         return 0;
     581                 :            : }
     582                 :            : 
     583                 :        448 : int fix_external_unix_sockets(void)
     584                 :            : {
     585                 :            :         struct unix_sk_desc *sk;
     586                 :            : 
     587                 :        448 :         pr_debug("Dumping external sockets\n");
     588                 :            : 
     589         [ +  + ]:        450 :         list_for_each_entry(sk, &unix_sockets, list) {
     590                 :          2 :                 UnixSkEntry e = UNIX_SK_ENTRY__INIT;
     591                 :          2 :                 FownEntry fown = FOWN_ENTRY__INIT;
     592                 :          2 :                 SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
     593                 :            : 
     594                 :          2 :                 show_one_unix("Dumping extern", sk);
     595                 :            : 
     596         [ -  + ]:          2 :                 BUG_ON(sk->sd.already_dumped);
     597                 :            : 
     598                 :          2 :                 fd_id_generate_special(NULL, &e.id);
     599                 :          2 :                 e.ino           = sk->sd.ino;
     600                 :          2 :                 e.type          = SOCK_DGRAM;
     601                 :          2 :                 e.state         = TCP_LISTEN;
     602                 :          2 :                 e.name.data     = (void *)sk->name;
     603                 :          2 :                 e.name.len      = (size_t)sk->namelen;
     604                 :          2 :                 e.uflags        = USK_EXTERN;
     605                 :          2 :                 e.peer          = 0;
     606                 :          2 :                 e.fown          = &fown;
     607                 :          2 :                 e.opts          = &skopts;
     608                 :            : 
     609         [ +  - ]:          2 :                 if (pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), &e, PB_UNIX_SK))
     610                 :            :                         goto err;
     611                 :            : 
     612                 :          2 :                 show_one_unix_img("Dumped extern", &e);
     613                 :            : 
     614         [ +  - ]:          2 :                 if (dump_external_sockets(sk))
     615                 :            :                         goto err;
     616                 :            :         }
     617                 :            : 
     618                 :            :         return 0;
     619                 :            : err:
     620                 :          0 :         return -1;
     621                 :            : }
     622                 :            : 
     623                 :            : struct unix_sk_info {
     624                 :            :         UnixSkEntry *ue;
     625                 :            :         struct list_head list;
     626                 :            :         char *name;
     627                 :            :         unsigned flags;
     628                 :            :         struct unix_sk_info *peer;
     629                 :            :         struct file_desc d;
     630                 :            :         futex_t bound;
     631                 :            : };
     632                 :            : 
     633                 :            : #define USK_PAIR_MASTER         0x1
     634                 :            : #define USK_PAIR_SLAVE          0x2
     635                 :            : 
     636                 :            : static struct unix_sk_info *find_unix_sk_by_ino(int ino)
     637                 :            : {
     638                 :            :         struct unix_sk_info *ui;
     639                 :            : 
     640         [ +  - ]:        112 :         list_for_each_entry(ui, &unix_sockets, list) {
     641         [ +  + ]:        112 :                 if (ui->ue->ino == ino)
     642                 :            :                         return ui;
     643                 :            :         }
     644                 :            : 
     645                 :            :         return NULL;
     646                 :            : }
     647                 :            : 
     648                 :         72 : static int shutdown_unix_sk(int sk, struct unix_sk_info *ui)
     649                 :            : {
     650                 :            :         int how;
     651                 :         36 :         UnixSkEntry *ue = ui->ue;
     652                 :            : 
     653 [ +  + ][ +  - ]:         36 :         if (!ue->has_shutdown || ue->shutdown == SK_SHUTDOWN__NONE)
     654                 :            :                 return 0;
     655                 :            : 
     656                 :         10 :         how = sk_decode_shutdown(ue->shutdown);
     657         [ -  + ]:         10 :         if (shutdown(sk, how)) {
     658                 :          0 :                 pr_perror("Can't shutdown unix socket");
     659                 :            :                 return -1;
     660                 :            :         }
     661                 :            : 
     662                 :         10 :         pr_debug("Socket %#x is shut down %d\n", ue->ino, how);
     663                 :            :         return 0;
     664                 :            : }
     665                 :            : 
     666                 :         60 : static int post_open_unix_sk(struct file_desc *d, int fd)
     667                 :            : {
     668                 :         10 :         struct unix_sk_info *ui;
     669                 :            :         struct unix_sk_info *peer;
     670                 :            :         struct sockaddr_un addr;
     671                 :            : 
     672                 :            :         ui = container_of(d, struct unix_sk_info, d);
     673         [ +  + ]:         60 :         if (ui->flags & (USK_PAIR_MASTER | USK_PAIR_SLAVE))
     674                 :            :                 return 0;
     675                 :            : 
     676                 :         24 :         peer = ui->peer;
     677                 :            : 
     678         [ +  + ]:         24 :         if (peer == NULL)
     679                 :            :                 return 0;
     680                 :            : 
     681         [ +  - ]:         10 :         if (ui->ue->uflags & USK_CALLBACK)
     682                 :            :                 return 0;
     683                 :            : 
     684                 :         10 :         pr_info("\tConnect %#x to %#x\n", ui->ue->ino, peer->ue->ino);
     685                 :            : 
     686                 :            :         /* Skip external sockets */
     687         [ +  + ]:         10 :         if (!list_empty(&peer->d.fd_info_head))
     688                 :          8 :                 futex_wait_while(&peer->bound, 0);
     689                 :            : 
     690                 :            :         memset(&addr, 0, sizeof(addr));
     691                 :         10 :         addr.sun_family = AF_UNIX;
     692                 :         10 :         memcpy(&addr.sun_path, peer->name, peer->ue->name.len);
     693                 :            : 
     694         [ -  + ]:         10 :         if (connect(fd, (struct sockaddr *)&addr,
     695                 :            :                                 sizeof(addr.sun_family) +
     696                 :         10 :                                 peer->ue->name.len) < 0) {
     697                 :          0 :                 pr_perror("Can't connect %#x socket", ui->ue->ino);
     698                 :          0 :                 return -1;
     699                 :            :         }
     700                 :            : 
     701         [ +  - ]:         10 :         if (restore_sk_queue(fd, peer->ue->id))
     702                 :            :                 return -1;
     703                 :            : 
     704         [ +  - ]:         10 :         if (rst_file_params(fd, ui->ue->fown, ui->ue->flags))
     705                 :            :                 return -1;
     706                 :            : 
     707         [ +  - ]:         10 :         if (restore_socket_opts(fd, ui->ue->opts))
     708                 :            :                 return -1;
     709                 :            : 
     710         [ +  - ]:         10 :         if (shutdown_unix_sk(fd, ui))
     711                 :            :                 return -1;
     712                 :            : 
     713                 :         10 :         return 0;
     714                 :            : }
     715                 :            : 
     716                 :         60 : static int bind_unix_sk(int sk, struct unix_sk_info *ui)
     717                 :            : {
     718                 :            :         struct sockaddr_un addr;
     719                 :            : 
     720         [ +  + ]:         60 :         if ((ui->ue->type == SOCK_STREAM) && (ui->ue->state == TCP_ESTABLISHED))
     721                 :            :                 /*
     722                 :            :                  * FIXME this can be done, but for doing this properly we
     723                 :            :                  * need to bind socket to its name, then rename one to
     724                 :            :                  * some temporary unique one and after all the sockets are
     725                 :            :                  * restored we should walk those temp names and rename
     726                 :            :                  * some of them back to real ones.
     727                 :            :                  */
     728                 :            :                 goto done;
     729                 :            : 
     730                 :            :         memset(&addr, 0, sizeof(addr));
     731                 :         36 :         addr.sun_family = AF_UNIX;
     732                 :         36 :         memcpy(&addr.sun_path, ui->name, ui->ue->name.len);
     733                 :            : 
     734         [ -  + ]:         36 :         if (bind(sk, (struct sockaddr *)&addr,
     735                 :         36 :                                 sizeof(addr.sun_family) + ui->ue->name.len)) {
     736                 :          0 :                 pr_perror("Can't bind socket");
     737                 :          0 :                 return -1;
     738                 :            :         }
     739                 :            : 
     740 [ +  + ][ +  + ]:         36 :         if (ui->ue->name.len && *ui->name && ui->ue->file_perms) {
                 [ +  - ]
     741                 :            :                 FilePermsEntry *perms = ui->ue->file_perms;
     742                 :            :                 char fname[PATH_MAX];
     743                 :            : 
     744         [ -  + ]:          8 :                 if (ui->ue->name.len >= sizeof(fname)) {
     745                 :          0 :                         pr_err("The file name is too long\n");
     746                 :          0 :                         return -1;
     747                 :            :                 }
     748                 :            : 
     749                 :            :                 memcpy(fname, ui->name, ui->ue->name.len);
     750                 :          8 :                 fname[ui->ue->name.len] = '\0';
     751                 :            : 
     752         [ -  + ]:          8 :                 if (chown(fname, perms->uid, perms->gid) == -1) {
     753                 :          0 :                         pr_perror("Unable to change file owner and group");
     754                 :          0 :                         return -1;
     755                 :            :                 }
     756                 :            : 
     757         [ -  + ]:          8 :                 if (chmod(fname, perms->mode) == -1) {
     758                 :          0 :                         pr_perror("Unable to change file mode bits");
     759                 :          8 :                         return -1;
     760                 :            :                 }
     761                 :            :         }
     762                 :            : 
     763                 :         36 :         futex_set_and_wake(&ui->bound, 1);
     764                 :            : done:
     765                 :            :         return 0;
     766                 :            : }
     767                 :            : 
     768                 :         60 : static int unixsk_should_open_transport(FdinfoEntry *fe,
     769                 :            :                                 struct file_desc *d)
     770                 :            : {
     771                 :            :         struct unix_sk_info *ui;
     772                 :            : 
     773                 :            :         ui = container_of(d, struct unix_sk_info, d);
     774                 :         60 :         return ui->flags & USK_PAIR_SLAVE;
     775                 :            : }
     776                 :            : 
     777                 :         18 : static int open_unixsk_pair_master(struct unix_sk_info *ui)
     778                 :            : {
     779                 :            :         int sk[2], tsk;
     780                 :         18 :         struct unix_sk_info *peer = ui->peer;
     781                 :            :         struct fdinfo_list_entry *fle;
     782                 :            : 
     783                 :         18 :         pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
     784                 :            :                         ui->ue->id, ui->ue->ino, ui->ue->peer);
     785                 :            : 
     786         [ -  + ]:         18 :         if (socketpair(PF_UNIX, ui->ue->type, 0, sk) < 0) {
     787                 :          0 :                 pr_perror("Can't make socketpair");
     788                 :          0 :                 return -1;
     789                 :            :         }
     790                 :            : 
     791         [ +  - ]:         18 :         if (restore_sk_queue(sk[0], peer->ue->id))
     792                 :            :                 return -1;
     793         [ +  - ]:         18 :         if (restore_sk_queue(sk[1], ui->ue->id))
     794                 :            :                 return -1;
     795                 :            : 
     796         [ +  - ]:         18 :         if (bind_unix_sk(sk[0], ui))
     797                 :            :                 return -1;
     798                 :            : 
     799         [ +  - ]:         18 :         if (rst_file_params(sk[0], ui->ue->fown, ui->ue->flags))
     800                 :            :                 return -1;
     801                 :            : 
     802         [ +  - ]:         18 :         if (restore_socket_opts(sk[0], ui->ue->opts))
     803                 :            :                 return -1;
     804                 :            : 
     805         [ +  - ]:         18 :         if (shutdown_unix_sk(sk[0], ui))
     806                 :            :                 return -1;
     807                 :            : 
     808                 :         18 :         tsk = socket(PF_UNIX, SOCK_DGRAM, 0);
     809         [ -  + ]:         18 :         if (tsk < 0) {
     810                 :          0 :                 pr_perror("Can't make transport socket");
     811                 :          0 :                 return -1;
     812                 :            :         }
     813                 :            : 
     814                 :         18 :         fle = file_master(&peer->d);
     815         [ -  + ]:         18 :         if (send_fd_to_peer(sk[1], fle, tsk)) {
     816                 :          0 :                 pr_err("Can't send pair slave\n");
     817                 :          0 :                 return -1;
     818                 :            :         }
     819                 :            : 
     820                 :         18 :         close(tsk);
     821                 :         18 :         close(sk[1]);
     822                 :            : 
     823                 :         18 :         return sk[0];
     824                 :            : }
     825                 :            : 
     826                 :         18 : static int open_unixsk_pair_slave(struct unix_sk_info *ui)
     827                 :            : {
     828                 :            :         struct fdinfo_list_entry *fle;
     829                 :            :         int sk;
     830                 :            : 
     831                 :         18 :         fle = file_master(&ui->d);
     832                 :            : 
     833                 :         18 :         pr_info("Opening pair slave (id %#x ino %#x peer %#x) on %d\n",
     834                 :            :                         ui->ue->id, ui->ue->ino, ui->ue->peer, fle->fe->fd);
     835                 :            : 
     836                 :         18 :         sk = recv_fd(fle->fe->fd);
     837         [ -  + ]:         18 :         if (sk < 0) {
     838                 :          0 :                 pr_err("Can't recv pair slave");
     839                 :          0 :                 return -1;
     840                 :            :         }
     841                 :         18 :         close(fle->fe->fd);
     842                 :            : 
     843         [ +  - ]:         18 :         if (bind_unix_sk(sk, ui))
     844                 :            :                 return -1;
     845                 :            : 
     846         [ +  - ]:         18 :         if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
     847                 :            :                 return -1;
     848                 :            : 
     849         [ +  - ]:         18 :         if (restore_socket_opts(sk, ui->ue->opts))
     850                 :            :                 return -1;
     851                 :            : 
     852         [ +  + ]:         18 :         if (ui->ue->type == SOCK_DGRAM)
     853                 :            :                 /*
     854                 :            :                  * Stream socket's "slave" end will be shut down
     855                 :            :                  * together with master
     856                 :            :                  */
     857         [ +  - ]:          8 :                 if (shutdown_unix_sk(sk, ui))
     858                 :            :                         return -1;
     859                 :            : 
     860                 :         18 :         return sk;
     861                 :            : }
     862                 :            : 
     863                 :         24 : static int open_unixsk_standalone(struct unix_sk_info *ui)
     864                 :            : {
     865                 :            :         int sk;
     866                 :            : 
     867                 :         24 :         pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
     868                 :            :                         ui->ue->id, ui->ue->ino, ui->ue->peer);
     869                 :            : 
     870                 :            :         /*
     871                 :            :          * Check if this socket was connected to criu service.
     872                 :            :          * If so, put response, that dumping and restoring
     873                 :            :          * was successful.
     874                 :            :          */
     875         [ -  + ]:         24 :         if (ui->ue->uflags & USK_SERVICE) {
     876                 :            :                 int sks[2];
     877                 :            : 
     878         [ #  # ]:          0 :                 if (socketpair(PF_UNIX, ui->ue->type, 0, sks)) {
     879                 :          0 :                         pr_perror("Can't create socketpair");
     880                 :          0 :                         return -1;
     881                 :            :                 }
     882                 :            : 
     883         [ #  # ]:          0 :                 if (send_criu_dump_resp(sks[1], true, true) == -1)
     884                 :            :                         return -1;
     885                 :            : 
     886                 :          0 :                 close(sks[1]);
     887                 :          0 :                 sk = sks[0];
     888 [ +  + ][ +  + ]:         26 :         } else if ((ui->ue->state == TCP_ESTABLISHED) && !ui->ue->peer) {
     889                 :            :                 int ret, sks[2];
     890                 :            : 
     891         [ -  + ]:          2 :                 if (ui->ue->type != SOCK_STREAM) {
     892                 :          0 :                         pr_err("Non-stream socket %x in established state\n",
     893                 :            :                                         ui->ue->ino);
     894                 :          0 :                         return -1;
     895                 :            :                 }
     896                 :            : 
     897         [ -  + ]:          2 :                 if (ui->ue->shutdown != SK_SHUTDOWN__BOTH) {
     898                 :          0 :                         pr_err("Wrong shutdown/peer state for %x\n",
     899                 :            :                                         ui->ue->ino);
     900                 :          0 :                         return -1;
     901                 :            :                 }
     902                 :            : 
     903                 :          2 :                 ret = socketpair(PF_UNIX, ui->ue->type, 0, sks);
     904         [ -  + ]:          2 :                 if (ret < 0) {
     905                 :          0 :                         pr_perror("Can't create socketpair");
     906                 :          0 :                         return -1;
     907                 :            :                 }
     908                 :            : 
     909                 :            :                 /*
     910                 :            :                  * Restore queue at the one end,
     911                 :            :                  * before closing the second one.
     912                 :            :                  */
     913         [ -  + ]:          2 :                 if (restore_sk_queue(sks[1], ui->ue->id)) {
     914                 :          0 :                         pr_perror("Can't restore socket queue");
     915                 :          0 :                         return -1;
     916                 :            :                 }
     917                 :            : 
     918                 :          2 :                 close(sks[1]);
     919                 :          2 :                 sk = sks[0];
     920                 :            :         } else {
     921         [ -  + ]:         22 :                 if (ui->ue->uflags & USK_CALLBACK) {
     922                 :          0 :                         sk = cr_plugin_restore_unix_sk(ui->ue->ino);
     923         [ #  # ]:          0 :                         if (sk >= 0)
     924                 :            :                                 goto out;
     925                 :            :                 }
     926                 :            : 
     927                 :            :                 /*
     928                 :            :                  * Connect to external sockets requires
     929                 :            :                  * special option to be passed.
     930                 :            :                  */
     931 [ +  + ][ +  + ]:         22 :                 if (ui->peer && (ui->peer->ue->uflags & USK_EXTERN) &&
                 [ -  + ]
     932                 :          2 :                                 !(opts.ext_unix_sk)) {
     933                 :          0 :                         pr_err("External socket found in image. "
     934                 :            :                                         "Consider using the --" USK_EXT_PARAM
     935                 :            :                                         "option to allow restoring it.\n");
     936                 :          0 :                         return -1;
     937                 :            :                 }
     938                 :            : 
     939                 :            : 
     940                 :         22 :                 sk = socket(PF_UNIX, ui->ue->type, 0);
     941         [ -  + ]:         22 :                 if (sk < 0) {
     942                 :          0 :                         pr_perror("Can't make unix socket");
     943                 :          0 :                         return -1;
     944                 :            :                 }
     945                 :            :         }
     946                 :            : 
     947         [ +  - ]:         24 :         if (bind_unix_sk(sk, ui))
     948                 :            :                 return -1;
     949                 :            : 
     950         [ +  + ]:         24 :         if (ui->ue->state == TCP_LISTEN) {
     951                 :          2 :                 pr_info("\tPutting %#x into listen state\n", ui->ue->ino);
     952         [ -  + ]:          2 :                 if (listen(sk, ui->ue->backlog) < 0) {
     953                 :          0 :                         pr_perror("Can't make usk listen");
     954                 :          0 :                         return -1;
     955                 :            :                 }
     956                 :            :         }
     957                 :            : out:
     958         [ +  - ]:         24 :         if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
     959                 :            :                 return -1;
     960                 :            : 
     961         [ +  - ]:         24 :         if (restore_socket_opts(sk, ui->ue->opts))
     962                 :            :                 return -1;
     963                 :            : 
     964                 :         24 :         return sk;
     965                 :            : }
     966                 :            : 
     967                 :         60 : static int open_unix_sk(struct file_desc *d)
     968                 :            : {
     969                 :            :         struct unix_sk_info *ui;
     970                 :            : 
     971                 :         60 :         ui = container_of(d, struct unix_sk_info, d);
     972         [ +  + ]:         60 :         if (ui->flags & USK_PAIR_MASTER)
     973                 :         18 :                 return open_unixsk_pair_master(ui);
     974         [ +  + ]:         42 :         else if (ui->flags & USK_PAIR_SLAVE)
     975                 :         18 :                 return open_unixsk_pair_slave(ui);
     976                 :            :         else
     977                 :         24 :                 return open_unixsk_standalone(ui);
     978                 :            : }
     979                 :            : 
     980                 :            : static struct file_desc_ops unix_desc_ops = {
     981                 :            :         .type = FD_TYPES__UNIXSK,
     982                 :            :         .open = open_unix_sk,
     983                 :            :         .post_open = post_open_unix_sk,
     984                 :            :         .want_transport = unixsk_should_open_transport,
     985                 :            : };
     986                 :            : 
     987                 :         62 : static int collect_one_unixsk(void *o, ProtobufCMessage *base)
     988                 :            : {
     989                 :            :         struct unix_sk_info *ui = o;
     990                 :            : 
     991                 :         62 :         ui->ue = pb_msg(base, UnixSkEntry);
     992                 :            : 
     993         [ +  + ]:         62 :         if (ui->ue->name.len) {
     994         [ -  + ]:         14 :                 if (ui->ue->name.len >= UNIX_PATH_MAX) {
     995                 :          0 :                         pr_err("Bad unix name len %d\n", (int)ui->ue->name.len);
     996                 :          0 :                         return -1;
     997                 :            :                 }
     998                 :            : 
     999                 :         14 :                 ui->name = (void *)ui->ue->name.data;
    1000                 :            : 
    1001                 :            :                 /*
    1002                 :            :                  * Make FS clean from sockets we're about to
    1003                 :            :                  * restore. See for how we bind them for details
    1004                 :            :                  */
    1005 [ +  + ][ +  + ]:         14 :                 if (ui->name[0] != '\0' &&
    1006                 :         12 :                                 !(ui->ue->uflags & USK_EXTERN))
    1007                 :         10 :                         unlink(ui->name);
    1008                 :            :         } else
    1009                 :         48 :                 ui->name = NULL;
    1010                 :            : 
    1011                 :            :         futex_init(&ui->bound);
    1012                 :         62 :         ui->peer = NULL;
    1013                 :         62 :         ui->flags = 0;
    1014 [ +  + ][ +  + ]:         62 :         pr_info(" `- Got %#x peer %#x (name %s)\n",
    1015                 :            :                 ui->ue->ino, ui->ue->peer,
    1016                 :            :                 ui->name ? (ui->name[0] ? ui->name : &ui->name[1]) : "-");
    1017                 :         62 :         list_add_tail(&ui->list, &unix_sockets);
    1018                 :         62 :         return file_desc_add(&ui->d, ui->ue->id, &unix_desc_ops);
    1019                 :            : }
    1020                 :            : 
    1021                 :            : struct collect_image_info unix_sk_cinfo = {
    1022                 :            :         .fd_type = CR_FD_UNIXSK,
    1023                 :            :         .pb_type = PB_UNIX_SK,
    1024                 :            :         .priv_size = sizeof(struct unix_sk_info),
    1025                 :            :         .collect = collect_one_unixsk,
    1026                 :            :         .flags = COLLECT_SHARED,
    1027                 :            : };
    1028                 :            : 
    1029                 :        354 : int collect_unix_sockets(void)
    1030                 :            : {
    1031                 :        354 :         return read_sk_queues();
    1032                 :            : }
    1033                 :            : 
    1034                 :        354 : int resolve_unix_peers(void)
    1035                 :            : {
    1036                 :            :         struct unix_sk_info *ui, *peer;
    1037                 :         18 :         struct fdinfo_list_entry *fle, *fle_peer;
    1038                 :            : 
    1039         [ +  + ]:        416 :         list_for_each_entry(ui, &unix_sockets, list) {
    1040         [ +  + ]:         62 :                 if (ui->peer)
    1041                 :         18 :                         continue;
    1042         [ +  + ]:         44 :                 if (!ui->ue->peer)
    1043                 :         16 :                         continue;
    1044                 :            : 
    1045                 :            :                 peer = find_unix_sk_by_ino(ui->ue->peer);
    1046                 :            : 
    1047         [ -  + ]:         28 :                 if (!peer) {
    1048                 :          0 :                         pr_err("FATAL: Peer %#x unresolved for %#x\n",
    1049                 :            :                                         ui->ue->peer, ui->ue->ino);
    1050                 :          0 :                         return -1;
    1051                 :            :                 }
    1052                 :            : 
    1053                 :         28 :                 ui->peer = peer;
    1054         [ +  + ]:         28 :                 if (ui == peer)
    1055                 :            :                         /* socket connected to self %) */
    1056                 :          2 :                         continue;
    1057         [ +  + ]:         26 :                 if (peer->ue->peer != ui->ue->ino)
    1058                 :          8 :                         continue;
    1059                 :            : 
    1060                 :            :                 /* socketpair or interconnected sockets */
    1061                 :         18 :                 peer->peer = ui;
    1062                 :            : 
    1063                 :            :                 /*
    1064                 :            :                  * Select who will restore the pair. Check is identical to
    1065                 :            :                  * the one in pipes.c and makes sure tasks wait for each other
    1066                 :            :                  * in pids sorting order (ascending).
    1067                 :            :                  */
    1068                 :            : 
    1069                 :         18 :                 fle = file_master(&ui->d);
    1070                 :         18 :                 fle_peer = file_master(&peer->d);
    1071                 :            : 
    1072         [ -  + ]:         18 :                 if (fdinfo_rst_prio(fle, fle_peer)) {
    1073                 :          0 :                         ui->flags |= USK_PAIR_MASTER;
    1074                 :          0 :                         peer->flags |= USK_PAIR_SLAVE;
    1075                 :            :                 } else {
    1076                 :         18 :                         peer->flags |= USK_PAIR_MASTER;
    1077                 :         18 :                         ui->flags |= USK_PAIR_SLAVE;
    1078                 :            :                 }
    1079                 :            :         }
    1080                 :            : 
    1081                 :        354 :         pr_info("Unix sockets:\n");
    1082         [ +  + ]:        416 :         list_for_each_entry(ui, &unix_sockets, list) {
    1083                 :            :                 struct fdinfo_list_entry *fle;
    1084                 :            : 
    1085         [ +  + ]:         62 :                 pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue->ino, ui->ue->peer,
    1086                 :            :                                 ui->peer ? ui->peer->ue->ino : 0, ui->flags);
    1087         [ +  + ]:        122 :                 list_for_each_entry(fle, &ui->d.fd_info_head, desc_list)
    1088                 :         60 :                         pr_info("\t\tfd %d in pid %d\n",
    1089                 :            :                                         fle->fe->fd, fle->pid);
    1090                 :            : 
    1091                 :            :         }
    1092                 :            : 
    1093                 :            :         return 0;
    1094                 :            : }
    1095                 :            : 

Generated by: LCOV version 1.9