Search code examples
c++linuxsocketsfile-descriptor

Sending and receiving integers array by Linux socket


I am trying to pass an array of integers (file descriptors) via linux socket using C++.

I used cmgs(3) and seccomp_unotify(2) to write the following send and receive functions:

send:

static bool send_fds(int socket)  // send array of fds by socket
{
  int myfds[] = {568, 519, 562, 572, 569 ,566}; //static values for testing
  struct msghdr msg = { 0 };
  struct cmsghdr *cmsg;
  char iobuf[1];
  struct iovec io = {
      .iov_base = iobuf,
      .iov_len = sizeof(iobuf)
  };
  union {
      char buf[CMSG_SPACE(sizeof(myfds))];
      struct cmsghdr align;
  } u;

  msg.msg_iov = &io;
  msg.msg_iovlen = 1;
  msg.msg_control = u.buf;
  msg.msg_controllen = sizeof(u.buf);
  
  cmsg = CMSG_FIRSTHDR(&msg);
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_RIGHTS;
  cmsg->cmsg_len = CMSG_LEN(sizeof(myfds));
  memcpy(CMSG_DATA(cmsg), &myfds, sizeof(myfds));

  if (sendmsg (socket, &msg, 0) < 0)
  {
    return false;
  }
  return true;
}

receive:

static int * read_fds(int sockfd)
{
  struct msghdr msgh;
  struct iovec iov;
  int data[6], fd[6];
  ssize_t nr;
  union {
      char   buf[CMSG_SPACE(sizeof(fd))];
      struct cmsghdr align;
  } controlMsg;
  struct cmsghdr *cmsgp;

  msgh.msg_name = NULL;
  msgh.msg_namelen = 0;
  msgh.msg_iov = &iov;
  msgh.msg_iovlen = 1;
  iov.iov_base = &data;
  iov.iov_len = sizeof(fd);
  msgh.msg_control = controlMsg.buf;
  msgh.msg_controllen = sizeof(controlMsg.buf);

  recvmsg(sockfd, &msgh, 0);

  cmsgp = CMSG_FIRSTHDR(&msgh);
  memcpy(&fd, CMSG_DATA(cmsgp), sizeof(int)*6);
  return fd;
}

No matter what I send, the array in the receive function is filled with [8,9,10,11,12,13].

What am I doing wrong?


Solution

  • From Cloudflare blog:

    Technically you do not send “file descriptors”. The “file descriptors” you handle in the code are simply indices into the processes' local file descriptor table, which in turn points into the OS' open file table, that finally points to the vnode representing the file. Thus the “file descriptor” observed by the other process will most likely have a different numeric value, despite pointing to the same file.