[PATCH libxxtrans 2/2] Fix alignment issues in FD passing code

Mark Kettenis mark.kettenis at xs4all.nl
Mon Nov 11 14:22:56 PST 2013


From: Mark Kettenis <kettenis at openbsd.org>

A char array on the stack is not guaranteed to have more than byte
alignment.  This means that casting it to a 'struct cmsghdr' and
accessing its members may result in unaligned access.  This will
generate SIGBUS on strict alignment architectures like OpenBSD/sparc64.
The solution is to use a union to force proper alignment.

Signed-off-by: Mark Kettenis <kettenis at openbsd.org>
---
 Xtranssock.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/Xtranssock.c b/Xtranssock.c
index 0370119..fdf1dd7 100644
--- a/Xtranssock.c
+++ b/Xtranssock.c
@@ -2197,9 +2197,9 @@ TRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close)
 
 #define MAX_FDS		128
 
-struct fd_pass {
+union fd_pass {
 	struct cmsghdr	cmsghdr;
-	int		fd[MAX_FDS];
+	char		buf[CMSG_SPACE(MAX_FDS * sizeof(int))];
 };
 
 #endif /* XTRANS_SEND_FDS */
@@ -2225,13 +2225,13 @@ TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
             .iov_base = buf,
             .iov_len = size
         };
-        char            cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)];
+        union fd_pass   cmsgbuf;
         struct msghdr   msg = {
             .msg_name = NULL,
             .msg_namelen = 0,
             .msg_iov = &iov,
             .msg_iovlen = 1,
-            .msg_control = cmsgbuf,
+            .msg_control = cmsgbuf.buf,
             .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
         };
 
@@ -2266,13 +2266,13 @@ TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
 
 #if XTRANS_SEND_FDS
     {
-        char            cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)];
+        union fd_pass   cmsgbuf;
         struct msghdr   msg = {
             .msg_name = NULL,
             .msg_namelen = 0,
             .msg_iov = buf,
             .msg_iovlen = size,
-            .msg_control = cmsgbuf,
+            .msg_control = cmsgbuf.buf,
             .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
         };
 
@@ -2308,7 +2308,7 @@ TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
 #if XTRANS_SEND_FDS
     if (ciptr->send_fds)
     {
-        char                    cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)];
+        union fd_pass           cmsgbuf;
         int                     nfd = nFd(&ciptr->send_fds);
         struct _XtransConnFd    *cf = ciptr->send_fds;
         struct msghdr           msg = {
@@ -2316,7 +2316,7 @@ TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
             .msg_namelen = 0,
             .msg_iov = buf,
             .msg_iovlen = size,
-            .msg_control = cmsgbuf,
+            .msg_control = cmsgbuf.buf,
             .msg_controllen = CMSG_LEN(nfd * sizeof(int))
         };
         struct cmsghdr          *hdr = CMSG_FIRSTHDR(&msg);
-- 
1.8.4.2



More information about the xorg-devel mailing list