From 1a65bbb8755fa1ae4a013bc1aa94c39297b8779e Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Thu, 12 Sep 2019 11:51:52 -0400 Subject: [PATCH] inet: fix: possible unaligned access in packed structure (inet/inet6) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Fix the warnings that unaligned pointers can be passed as parameters emitted when building inet.c and inet6.c. Signed-off-by: Jérémie Galarneau --- src/common/macros.h | 7 +++++++ src/common/sessiond-comm/inet.c | 33 ++++++++++++++++++++----------- src/common/sessiond-comm/inet6.c | 34 ++++++++++++++++++++------------ 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/common/macros.h b/src/common/macros.h index f242da481..2120c64ef 100644 --- a/src/common/macros.h +++ b/src/common/macros.h @@ -108,6 +108,13 @@ void *zmalloc(size_t len) #define ASSERT_LOCKED(lock) assert(pthread_mutex_trylock(&lock)) +/* + * Get an aligned pointer to a value. This is meant + * as a helper to pass an aligned pointer to a member in a packed structure + * to a function. + */ +#define ALIGNED_CONST_PTR(value) (((const typeof(value) []) { value })) + /* * lttng_strncpy returns 0 on success, or nonzero on failure. * It checks that the @src string fits into @dst_len before performing diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c index 57ffbe45c..d107ced28 100644 --- a/src/common/sessiond-comm/inet.c +++ b/src/common/sessiond-comm/inet.c @@ -101,14 +101,17 @@ LTTNG_HIDDEN int lttcomm_bind_inet_sock(struct lttcomm_sock *sock) { return bind(sock->fd, - (const struct sockaddr *) &sock->sockaddr.addr.sin, + (const struct sockaddr *) ALIGNED_CONST_PTR( + sock->sockaddr.addr.sin), sizeof(sock->sockaddr.addr.sin)); } static int connect_no_timeout(struct lttcomm_sock *sock) { - return connect(sock->fd, (struct sockaddr *) &sock->sockaddr.addr.sin, + return connect(sock->fd, + (const struct sockaddr *) ALIGNED_CONST_PTR( + sock->sockaddr.addr.sin), sizeof(sock->sockaddr.addr.sin)); } @@ -141,11 +144,11 @@ int connect_with_timeout(struct lttcomm_sock *sock) } connect_ret = connect(sock->fd, - (struct sockaddr *) &sock->sockaddr.addr.sin, - sizeof(sock->sockaddr.addr.sin)); - if (connect_ret == -1 && errno != EAGAIN - && errno != EWOULDBLOCK - && errno != EINPROGRESS) { + (const struct sockaddr *) ALIGNED_CONST_PTR( + sock->sockaddr.addr.sin), + sizeof(sock->sockaddr.addr.sin)); + if (connect_ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK && + errno != EINPROGRESS) { goto error; } else if (!connect_ret) { /* Connect succeeded */ @@ -261,6 +264,7 @@ struct lttcomm_sock *lttcomm_accept_inet_sock(struct lttcomm_sock *sock) socklen_t len; struct lttcomm_sock *new_sock; unsigned long timeout; + struct sockaddr_in new_addr = {}; if (sock->proto == LTTCOMM_SOCK_UDP) { /* @@ -275,15 +279,15 @@ struct lttcomm_sock *lttcomm_accept_inet_sock(struct lttcomm_sock *sock) goto error; } - len = sizeof(new_sock->sockaddr.addr.sin); + len = sizeof(new_addr); /* Blocking call */ - new_fd = accept(sock->fd, (struct sockaddr *) &new_sock->sockaddr.addr.sin, - &len); + new_fd = accept(sock->fd, (struct sockaddr *) &new_addr, &len); if (new_fd < 0) { PERROR("accept inet"); goto error; } + new_sock->sockaddr.addr.sin = new_addr; timeout = lttcomm_get_network_timeout(); if (timeout) { int ret; @@ -356,6 +360,7 @@ ssize_t lttcomm_recvmsg_inet_sock(struct lttcomm_sock *sock, void *buf, struct iovec iov[1]; ssize_t ret = -1; size_t len_last; + struct sockaddr_in addr = sock->sockaddr.addr.sin; memset(&msg, 0, sizeof(msg)); @@ -364,7 +369,7 @@ ssize_t lttcomm_recvmsg_inet_sock(struct lttcomm_sock *sock, void *buf, msg.msg_iov = iov; msg.msg_iovlen = 1; - msg.msg_name = (struct sockaddr *) &sock->sockaddr.addr.sin; + msg.msg_name = (struct sockaddr *) &addr; msg.msg_namelen = sizeof(sock->sockaddr.addr.sin); do { @@ -421,9 +426,13 @@ ssize_t lttcomm_sendmsg_inet_sock(struct lttcomm_sock *sock, const void *buf, switch (sock->proto) { case LTTCOMM_SOCK_UDP: - msg.msg_name = (struct sockaddr *) &sock->sockaddr.addr.sin; + { + struct sockaddr_in addr = sock->sockaddr.addr.sin; + + msg.msg_name = (struct sockaddr *) &addr; msg.msg_namelen = sizeof(sock->sockaddr.addr.sin); break; + } default: break; } diff --git a/src/common/sessiond-comm/inet6.c b/src/common/sessiond-comm/inet6.c index 03b6627d1..66a4b552f 100644 --- a/src/common/sessiond-comm/inet6.c +++ b/src/common/sessiond-comm/inet6.c @@ -99,14 +99,17 @@ LTTNG_HIDDEN int lttcomm_bind_inet6_sock(struct lttcomm_sock *sock) { return bind(sock->fd, - (const struct sockaddr *) &sock->sockaddr.addr.sin6, + (const struct sockaddr *) ALIGNED_CONST_PTR( + sock->sockaddr.addr.sin6), sizeof(sock->sockaddr.addr.sin6)); } static int connect_no_timeout(struct lttcomm_sock *sock) { - return connect(sock->fd, (struct sockaddr *) &sock->sockaddr.addr.sin6, + return connect(sock->fd, + (const struct sockaddr *) ALIGNED_CONST_PTR( + sock->sockaddr.addr.sin6), sizeof(sock->sockaddr.addr.sin6)); } @@ -139,11 +142,11 @@ int connect_with_timeout(struct lttcomm_sock *sock) } connect_ret = connect(sock->fd, - (struct sockaddr *) &sock->sockaddr.addr.sin6, - sizeof(sock->sockaddr.addr.sin6)); - if (connect_ret == -1 && errno != EAGAIN - && errno != EWOULDBLOCK - && errno != EINPROGRESS) { + (const struct sockaddr *) ALIGNED_CONST_PTR( + sock->sockaddr.addr.sin6), + sizeof(sock->sockaddr.addr.sin6)); + if (connect_ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK && + errno != EINPROGRESS) { goto error; } else if (!connect_ret) { /* Connect succeeded */ @@ -259,6 +262,7 @@ struct lttcomm_sock *lttcomm_accept_inet6_sock(struct lttcomm_sock *sock) int new_fd; socklen_t len; struct lttcomm_sock *new_sock; + struct sockaddr_in6 new_addr = {}; if (sock->proto == LTTCOMM_SOCK_UDP) { /* @@ -273,16 +277,15 @@ struct lttcomm_sock *lttcomm_accept_inet6_sock(struct lttcomm_sock *sock) goto error; } - len = sizeof(new_sock->sockaddr.addr.sin6); + len = sizeof(new_addr); /* Blocking call */ - new_fd = accept(sock->fd, - (struct sockaddr *) &new_sock->sockaddr.addr.sin6, &len); + new_fd = accept(sock->fd, (struct sockaddr *) &new_addr, &len); if (new_fd < 0) { PERROR("accept inet6"); goto error; } - + new_sock->sockaddr.addr.sin6 = new_addr; new_sock->fd = new_fd; new_sock->ops = &inet6_ops; @@ -336,6 +339,7 @@ ssize_t lttcomm_recvmsg_inet6_sock(struct lttcomm_sock *sock, void *buf, struct iovec iov[1]; ssize_t ret = -1; size_t len_last; + struct sockaddr_in6 addr = sock->sockaddr.addr.sin6; memset(&msg, 0, sizeof(msg)); @@ -344,7 +348,7 @@ ssize_t lttcomm_recvmsg_inet6_sock(struct lttcomm_sock *sock, void *buf, msg.msg_iov = iov; msg.msg_iovlen = 1; - msg.msg_name = (struct sockaddr *) &sock->sockaddr.addr.sin6; + msg.msg_name = (struct sockaddr *) &addr; msg.msg_namelen = sizeof(sock->sockaddr.addr.sin6); do { @@ -391,9 +395,13 @@ ssize_t lttcomm_sendmsg_inet6_sock(struct lttcomm_sock *sock, const void *buf, switch (sock->proto) { case LTTCOMM_SOCK_UDP: - msg.msg_name = (struct sockaddr *) &sock->sockaddr.addr.sin6; + { + struct sockaddr_in6 addr = sock->sockaddr.addr.sin6; + + msg.msg_name = (struct sockaddr *) &addr; msg.msg_namelen = sizeof(sock->sockaddr.addr.sin6); break; + } default: break; } -- 2.34.1