The code in src/fdpass.C to construct control data buffers for socket
message ancillary data fails to allocate and align sufficient space
according to the way the API is to be used, causing the passage of
file descriptors to fail on platforms, such as the PowerPC, that have
more stringent alignment requirements than the x86.  Attached is a
patch to allocate and align sufficient space.

This patch uses malloc and free rather than a stack-allocated buffer
so that guaranteeing alignment is simpler (malloc already does it; a
stack-allocated buffer would require a union with a struct cmsghdr
member to guarantee alignment), and because on some systems (NetBSD)
the macros CMSG_SPACE and CMSG_LEN expand to non-constant expressions.
--- src/fdpass.C.orig   2007-06-25 23:47:14.000000000 +0000
+++ src/fdpass.C        2008-08-09 00:41:29.000000000 +0000
@@ -26,6 +26,7 @@
 #include "../config.h"
 
 #include <cstddef> // needed by broken bsds for NULL used in sys/uio.h
+#include <cstdlib>
 
 #include <sys/types.h>
 #include <sys/uio.h>
@@ -33,7 +34,12 @@
 
 #include "libptytty.h"
 
-#ifndef CMSG_LEN // CMSG_SPACE && CMSG_LEN are rfc2292 extensions to unix
+// CMSG_SPACE & CMSG_LEN are rfc2292 extensions to unix
+#ifndef CMSG_SPACE
+# define CMSG_SPACE(len) (sizeof (cmsghdr) + len)
+#endif
+
+#ifndef CMSG_LEN
 # define CMSG_LEN(len) (sizeof (cmsghdr) + len)
 #endif
 
@@ -42,9 +48,13 @@ ptytty::send_fd (int socket, int fd)
 {
   msghdr msg;
   iovec iov;
-  char buf [CMSG_LEN (sizeof (int))];
+  void *buf;
+  cmsghdr *cmsg;
   char data = 0;
 
+  if ((buf = malloc (CMSG_SPACE (sizeof (int)))) == NULL)
+    return 0;
+
   iov.iov_base = &data;
   iov.iov_len  = 1;
 
@@ -52,19 +62,19 @@ ptytty::send_fd (int socket, int fd)
   msg.msg_namelen    = 0;
   msg.msg_iov        = &iov;
   msg.msg_iovlen     = 1;
-  msg.msg_control    = (void *)buf;
-  msg.msg_controllen = sizeof buf;
+  msg.msg_control    = buf;
+  msg.msg_controllen = CMSG_SPACE (sizeof (int));
 
-  cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
+  cmsg = CMSG_FIRSTHDR (&msg);
   cmsg->cmsg_level = SOL_SOCKET;
   cmsg->cmsg_type  = SCM_RIGHTS;
   cmsg->cmsg_len   = CMSG_LEN (sizeof (int));
 
   *(int *)CMSG_DATA (cmsg) = fd;
 
-  msg.msg_controllen = cmsg->cmsg_len;
-
-  return sendmsg (socket, &msg, 0) >= 0;
+  ssize_t result = sendmsg (socket, &msg, 0);
+  free (buf);
+  return result >= 0;
 }
 
 int
@@ -72,8 +82,13 @@ ptytty::recv_fd (int socket)
 {
   msghdr msg;
   iovec iov;
-  char buf [CMSG_LEN (sizeof (int))];  /* ancillary data buffer */
+  void *buf;
+  cmsghdr *cmsg;
   char data = 1;
+  int fd = -1;
+
+  if ((buf = malloc (CMSG_SPACE (sizeof (int)))) == NULL)
+    return -1;
 
   iov.iov_base = &data;
   iov.iov_len  = 1;
@@ -83,23 +98,23 @@ ptytty::recv_fd (int socket)
   msg.msg_iov        = &iov;
   msg.msg_iovlen     = 1;
   msg.msg_control    = buf;
-  msg.msg_controllen = sizeof buf;
-
-  cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
-  cmsg->cmsg_level = SOL_SOCKET;
-  cmsg->cmsg_type  = SCM_RIGHTS;
-  cmsg->cmsg_len   = CMSG_LEN (sizeof (int));
-
-  msg.msg_controllen = cmsg->cmsg_len;
+  msg.msg_controllen = CMSG_SPACE (sizeof (int));
 
   if (recvmsg (socket, &msg, 0) <= 0
       || data               != 0
-      || msg.msg_controllen < CMSG_LEN (sizeof (int))
-      || cmsg->cmsg_level   != SOL_SOCKET
+      || msg.msg_controllen < CMSG_SPACE (sizeof (int)))
+    goto exit;
+
+  cmsg = CMSG_FIRSTHDR (&msg);
+  if (cmsg->cmsg_level      != SOL_SOCKET
       || cmsg->cmsg_type    != SCM_RIGHTS
       || cmsg->cmsg_len     < CMSG_LEN (sizeof (int)))
-    return -1;
+    goto exit;
+
+  fd = *(int *)CMSG_DATA (cmsg);
 
-  return *(int *)CMSG_DATA (cmsg);
+ exit:
+  free (buf);
+  return fd;
 }
_______________________________________________
rxvt-unicode mailing list
rxvt-unicode@lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/rxvt-unicode

Reply via email to