diff options
author | Mark Kettenis <kettenis@openbsd.org> | 2013-11-11 23:18:01 +0100 |
---|---|---|
committer | Mark Kettenis <kettenis@openbsd.org> | 2013-11-21 11:35:07 +0100 |
commit | 8b2c8aabe27bcaa4de6432b53c4a1296010ea823 (patch) | |
tree | 626309e9ad944add252ded40bb9ff6e74d93d33c | |
parent | 81662d2018a35a161a5e9707563ee7f503f8d3e0 (diff) |
Fix alignment issues in FD passing code
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@openbsd.org>
Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
-rw-r--r-- | Xtranssock.c | 16 |
1 files 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); |