Bug 69516 - LTC1053-problem with send/recv through sockets
LTC1053-problem with send/recv through sockets
Status: CLOSED ERRATA
Product: Red Hat Linux
Classification: Retired
Component: kernel (Show other bugs)
7.2
ia64 Linux
high Severity high
: ---
: ---
Assigned To: Larry Woodman
Brian Brock
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2002-07-22 17:57 EDT by IBM Bug Proxy
Modified: 2005-10-31 17:00 EST (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2003-12-16 20:05:48 EST
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:


Attachments (Terms of Use)

  None (edit)
Description IBM Bug Proxy 2002-07-22 17:57:44 EDT
ia64, RedHat 7.2, Kernel: 2.4.9-18custom

We are passing filedescriptors through sockets, but the length of the messages
seem to be rounded up to 8-byte boundaries on the receive end, despite the fact
that this is not what we want.  The attached testcase, socktest.C, seems to
demonstrate is that the msg_controllen parameter used in recvmsg() is adjusted
in increments of 8-bytes, but since the file-descriptors are represented by
4-byte values, we cannot extract the necessary information from the controllen:

The test does the following:

(1) Create a domain socket pair
(2) Fork
(3) One process will send three messages to the other through the socketpair
(4) Each message contains 4 bytes of information, and 1, then 2, then 3
file-descriptors

The testcase outputs some information, including the controllen on the sending
side, and the receiving side. The controllen before the sendmsg(), and after the
recvmsg() should match, but the testcase shows that we seem to be incorrectly
rounding the value up to the nearest 8-byte boundary.

Please copy David Kalmuk (dckalmuk@ca.ibm.com) on all correspondence.  He does
not have a bugzilla account.

--------cut here socktest.C----------
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socketvar.h>

#define CMSG_SPACE(_x) (sizeof(struct cmsghdr)+(_x))
#define CMSG_LEN(_x) CMSG_SPACE(_x)

#define domainSocketPair(_a) socketpair(AF_UNIX,     \
                                        SOCK_STREAM, \
                                        0,           \
                                        (_a))
#define SOCK_MAX_FD 3

typedef struct
{
    int   fd[SOCK_MAX_FD];
    int   num_fd;
    void* buff;
    int   buff_lng;
}SOCK_MSG;


int sockSendMsg(SOCK_MSG* pParmData,
                int       sock)
{
  int rc = 0;
  int count;
  int num_fd = pParmData->num_fd;
  struct msghdr msg;
  struct iovec iov[1];
  int* pData;

  union
  {
    struct cmsghdr cm;
    char control[CMSG_SPACE((sizeof(int)*SOCK_MAX_FD))];
  }control_un;

  struct cmsghdr *cmptr;

  msg.msg_control = &control_un.cm;
  msg.msg_flags  = 0;
  msg.msg_controllen = sizeof(cmsghdr) + (sizeof(int)*num_fd);

  cmptr             = CMSG_FIRSTHDR(&msg);
  cmptr->cmsg_len   = CMSG_LEN(sizeof(int) * num_fd);
  cmptr->cmsg_level = SOL_SOCKET;
  cmptr->cmsg_type  = SCM_RIGHTS;
  pData = (int*)CMSG_DATA(cmptr);

  for (count = 0; count < num_fd; count++)
  {
    *pData = pParmData->fd[count];
    pData++;
  }

  msg.msg_name   = (caddr_t) 0;
  msg.msg_namelen = 0;

  iov[0].iov_base = (char*)pParmData->buff;
  iov[0].iov_len  = pParmData->buff_lng;

  msg.msg_iov    = iov;
  msg.msg_iovlen = 1;

  printf("Sending %d descriptors\n", pParmData->num_fd);
  printf("Sending Controllen: %d\n", msg.msg_controllen);

  rc = sendmsg(sock, &msg, 0);

  printf("Send rc: %d\n", rc);

  return rc;
}

int sockRecvMsg(SOCK_MSG* pParmData,
                int       sock)
{
  int rc = 0;
  struct msghdr msg;
  struct iovec iov[1];
  int count;
  int* pData;

  union
  {
    struct cmsghdr cm;
    char control[CMSG_SPACE((sizeof(int)*SOCK_MAX_FD))];
  }control_un;

  struct cmsghdr *cmptr;

  msg.msg_control = &control_un.cm;
  msg.msg_controllen = sizeof(control_un);
  msg.msg_flags = 0;

  cmptr = CMSG_FIRSTHDR(&msg);

  msg.msg_name = NULL;
  msg.msg_namelen = 0;

  iov[0].iov_base = (char*)pParmData->buff;
  iov[0].iov_len = pParmData->buff_lng;

  msg.msg_iov = iov;
  msg.msg_iovlen = 1;

  printf("Receive Controllen: %d\n", msg.msg_controllen);

  rc = recvmsg(sock, &msg, 0);

  printf("Recv rc: %d\n", rc);
  printf("Received Controllen: %d\n", msg.msg_controllen);

  if (rc > 0)
  {
     pData = (int*)CMSG_DATA(cmptr);

     count = 0;
     while(msg.msg_controllen > sizeof(cmsghdr))
     {
        pParmData->fd[count] = *pData;
        pData++;
        msg.msg_controllen -= sizeof(int);
        count++;
     }
  }

  return rc;
}

int main()
{
   int pair[2];
   int rc;
   int testData = 3;

   SOCK_MSG msgData;

   domainSocketPair(pair);

   msgData.fd[0]  = pair[0];
   msgData.fd[1]  = pair[1];
   msgData.fd[2]  = pair[0];
   msgData.num_fd = 1;

   msgData.buff = &testData;
   msgData.buff_lng = sizeof(testData);

   if (fork() == 0)
   {
      sockSendMsg(&msgData,
                  pair[0]);

      msgData.num_fd = 2;
      sleep(5);
      sockSendMsg(&msgData,
                  pair[0]);

      msgData.num_fd = 3;
      sleep(5);
      sockSendMsg(&msgData,
                  pair[0]);
   }
   else
   {
      sockRecvMsg(&msgData,
                  pair[1]);

      printf("Received: %d %d\n", msgData.fd[0], *((int*)msgData.buff));

      sockRecvMsg(&msgData,
                  pair[1]);
      printf("Received: %d %d %d\n", msgData.fd[0], msgData.fd[1],
*((int*)msgData.buff));

      sockRecvMsg(&msgData,
                  pair[1]);
      printf("Received: %d %d %d\n", msgData.fd[0], msgData.fd[1],
*((int*)msgData.buff));
   }

   return 0;
}

--------cut here----------------
Comment 1 Arjan van de Ven 2002-08-22 08:40:32 EDT
the latest kernel for 7.2/IA64 is 2.4.9-31......... please use that
Comment 2 Larry Woodman 2003-06-23 13:45:26 EDT
Fixed in 2.4.18-e.18.

Larry Woodman

Note You need to log in before you can comment on or make changes to this bug.