LCOV - code coverage report
Current view: top level - crtools - util-net.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 40 58 69.0 %
Date: 2012-12-28 Functions: 2 2 100.0 %
Branches: 20 46 43.5 %

           Branch data     Line data    Source code
       1                 :            : #include <sys/socket.h>
       2                 :            : #include <sys/un.h>
       3                 :            : 
       4                 :            : #include <errno.h>
       5                 :            : 
       6                 :            : #include "compiler.h"
       7                 :            : #include "memcpy_64.h"
       8                 :            : #include "types.h"
       9                 :            : #include "syscall.h"
      10                 :            : 
      11                 :            : #include "util-net.h"
      12                 :            : 
      13                 :            : static void scm_fdset_init_chunk(struct scm_fdset *fdset, int nr_fds)
      14                 :            : {
      15                 :            :         struct cmsghdr *cmsg;
      16                 :            : 
      17                 :       2175 :         fdset->hdr.msg_controllen = CMSG_LEN(sizeof(int) * nr_fds);
      18                 :            : 
      19 [ +  - ][ +  - ]:       2175 :         cmsg            = CMSG_FIRSTHDR(&fdset->hdr);
      20                 :       2175 :         cmsg->cmsg_len       = fdset->hdr.msg_controllen;
      21                 :            : }
      22                 :            : 
      23                 :            : static int *scm_fdset_init(struct scm_fdset *fdset, struct sockaddr_un *saddr,
      24                 :            :                 int saddr_len, bool with_flags)
      25                 :            : {
      26                 :            :         struct cmsghdr *cmsg;
      27                 :            : 
      28                 :            :         BUILD_BUG_ON(CR_SCM_MAX_FD > SCM_MAX_FD);
      29                 :            :         BUILD_BUG_ON(sizeof(fdset->msg_buf) < (CMSG_SPACE(sizeof(int) * CR_SCM_MAX_FD)));
      30                 :            : 
      31                 :       2175 :         fdset->iov.iov_base          = fdset->opts;
      32 [ +  + ][ +  - ]:       2175 :         fdset->iov.iov_len           = with_flags ? sizeof(fdset->opts) : 1;
      33                 :            : 
      34                 :       2175 :         fdset->hdr.msg_iov           = &fdset->iov;
      35                 :       2175 :         fdset->hdr.msg_iovlen                = 1;
      36                 :       2175 :         fdset->hdr.msg_name          = (struct sockaddr *)saddr;
      37                 :       2175 :         fdset->hdr.msg_namelen               = saddr_len;
      38                 :            : 
      39                 :       2175 :         fdset->hdr.msg_control               = &fdset->msg_buf;
      40                 :       2175 :         fdset->hdr.msg_controllen    = CMSG_LEN(sizeof(int) * CR_SCM_MAX_FD);
      41                 :            : 
      42                 :       2175 :         cmsg                            = CMSG_FIRSTHDR(&fdset->hdr);
      43                 :       2175 :         cmsg->cmsg_len                       = fdset->hdr.msg_controllen;
      44                 :       2175 :         cmsg->cmsg_level             = SOL_SOCKET;
      45                 :       2175 :         cmsg->cmsg_type                      = SCM_RIGHTS;
      46                 :            : 
      47                 :            :         return (int *)CMSG_DATA(cmsg);
      48                 :            : }
      49                 :            : 
      50                 :       1224 : int send_fds(int sock, struct sockaddr_un *saddr, int len,
      51                 :            :                 int *fds, int nr_fds, bool with_flags)
      52                 :            : {
      53                 :            :         struct scm_fdset fdset;
      54                 :            :         int *cmsg_data;
      55                 :            :         int i, min_fd, ret;
      56                 :            : 
      57                 :       2448 :         cmsg_data = scm_fdset_init(&fdset, saddr, len, with_flags);
      58         [ +  + ]:       2448 :         for (i = 0; i < nr_fds; i += min_fd) {
      59                 :       1224 :                 min_fd = min(CR_SCM_MAX_FD, nr_fds - i);
      60                 :       1224 :                 scm_fdset_init_chunk(&fdset, min_fd);
      61                 :       1224 :                 builtin_memcpy(cmsg_data, &fds[i], sizeof(int) * min_fd);
      62                 :            : 
      63         [ -  + ]:       1224 :                 if (with_flags) {
      64                 :            :                         int j;
      65                 :            : 
      66         [ #  # ]:          0 :                         for (j = 0; j < min_fd; j++) {
      67                 :          0 :                                 int flags, fd = fds[i + j];
      68                 :          0 :                                 struct fd_opts *p = fdset.opts + j;
      69                 :            :                                 struct f_owner_ex owner_ex;
      70                 :            :                                 u32 v[2];
      71                 :            : 
      72                 :          0 :                                 flags = sys_fcntl(fd, F_GETFD, 0);
      73         [ #  # ]:          0 :                                 if (flags < 0)
      74                 :            :                                         return -1;
      75                 :            : 
      76                 :          0 :                                 p->flags = (char)flags;
      77                 :            : 
      78         [ #  # ]:          0 :                                 if (sys_fcntl(fd, F_GETOWN_EX, (long)&owner_ex))
      79                 :            :                                         return -1;
      80                 :            : 
      81                 :            :                                 /*
      82                 :            :                                  * Simple case -- nothing is changed.
      83                 :            :                                  */
      84         [ #  # ]:          0 :                                 if (owner_ex.pid == 0) {
      85                 :          0 :                                         p->fown.pid = 0;
      86                 :          0 :                                         continue;
      87                 :            :                                 }
      88                 :            : 
      89         [ #  # ]:          0 :                                 if (sys_fcntl(fd, F_GETOWNER_UIDS, (long)&v))
      90                 :            :                                         return -1;
      91                 :            : 
      92                 :          0 :                                 p->fown.uid   = v[0];
      93                 :          0 :                                 p->fown.euid  = v[1];
      94                 :          0 :                                 p->fown.pid_type = owner_ex.type;
      95                 :          0 :                                 p->fown.pid   = owner_ex.pid;
      96                 :            :                         }
      97                 :            :                 }
      98                 :            : 
      99                 :       1224 :                 ret = sys_sendmsg(sock, &fdset.hdr, 0);
     100         [ -  + ]:       1224 :                 if (ret <= 0)
     101         [ #  # ]:          0 :                         return ret ? : -1;
     102                 :            :         }
     103                 :            : 
     104                 :            :         return 0;
     105                 :            : }
     106                 :            : 
     107                 :        951 : int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts)
     108                 :            : {
     109                 :            :         struct scm_fdset fdset;
     110                 :            :         struct cmsghdr *cmsg;
     111                 :            :         int *cmsg_data;
     112                 :            :         int ret;
     113                 :            :         int i, min_fd;
     114                 :            : 
     115                 :       1902 :         cmsg_data = scm_fdset_init(&fdset, NULL, 0, opts != NULL);
     116         [ +  + ]:       1902 :         for (i = 0; i < nr_fds; i += min_fd) {
     117                 :        951 :                 min_fd = min(CR_SCM_MAX_FD, nr_fds - i);
     118                 :        951 :                 scm_fdset_init_chunk(&fdset, min_fd);
     119                 :            : 
     120                 :        951 :                 ret = sys_recvmsg(sock, &fdset.hdr, 0);
     121         [ -  + ]:        951 :                 if (ret <= 0)
     122         [ #  # ]:          0 :                         return ret ? : -1;
     123                 :            : 
     124         [ +  - ]:        951 :                 cmsg = CMSG_FIRSTHDR(&fdset.hdr);
     125 [ +  - ][ +  - ]:        951 :                 if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS)
     126                 :            :                         return -EINVAL;
     127         [ +  - ]:        951 :                 if (fdset.hdr.msg_flags & MSG_CTRUNC)
     128                 :            :                         return -ENFILE;
     129                 :            : 
     130                 :        951 :                 min_fd = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
     131                 :            :                 /*
     132                 :            :                  * In case if kernel screwed the recepient, most probably
     133                 :            :                  * the caller stack frame will be overwriten, just scream
     134                 :            :                  * and exit.
     135                 :            :                  *
     136                 :            :                  * FIXME Need to sanitize util.h to be able to include it
     137                 :            :                  * into files which do not have glibc and a couple of
     138                 :            :                  * sys_write_ helpers. Meawhile opencoded BUG_ON here.
     139                 :            :                  */
     140         [ -  + ]:        951 :                 if (unlikely(min_fd > CR_SCM_MAX_FD))
     141                 :          0 :                         *(volatile unsigned long *)NULL = 0xdead0000 + __LINE__;
     142         [ +  - ]:        951 :                 if (unlikely(min_fd <= 0))
     143                 :            :                         return -1;
     144                 :        951 :                 builtin_memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd);
     145         [ +  + ]:        951 :                 if (opts)
     146                 :        349 :                         builtin_memcpy(opts + i, fdset.opts, sizeof(struct fd_opts) * min_fd);
     147                 :            :         }
     148                 :            : 
     149                 :            :         return 0;
     150                 :            : }
     151                 :            : 

Generated by: LCOV version 1.9