From: Mathieu Desnoyers Date: Thu, 21 Jul 2011 18:16:05 +0000 (-0400) Subject: Fix sending fd through sendmsg/recvmsg ancillary data X-Git-Tag: v2.0-pre2~9 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=159c7ff4ea99cd808f89787f66a23152483137d4 Fix sending fd through sendmsg/recvmsg ancillary data ltt-kconsumerd was only reading a "char" rather than an integer. It worked fine on little endian for values below 256, and failed on big endian machines (always reading "0"). Also cleanup msg initialization. Also perform final msg.msg_controllen = cmsg->cmsg_len; after memcpy, as done in cmsg(3) example (extra safety). Signed-off-by: Mathieu Desnoyers --- diff --git a/liblttkconsumerd/liblttkconsumerd.c b/liblttkconsumerd/liblttkconsumerd.c index 1e86d28d0..1d69a4c46 100644 --- a/liblttkconsumerd/liblttkconsumerd.c +++ b/liblttkconsumerd/liblttkconsumerd.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "libkernelctl.h" #include "liblttkconsumerd.h" @@ -585,7 +586,6 @@ static int kconsumerd_consumerd_recv_fd(int sfd, struct pollfd *kconsumerd_sockpoll, int size, enum kconsumerd_command cmd_type) { - struct msghdr msg; struct iovec iov[1]; int ret = 0, i, tmp2; struct cmsghdr *cmsg; @@ -596,8 +596,15 @@ static int kconsumerd_consumerd_recv_fd(int sfd, /* the number of fds we are about to receive */ nb_fd = size / sizeof(struct lttcomm_kconsumerd_msg); + /* + * Note: only supporting receiving one FD at a time for now. + * This code needs fixing if we wish to receive more (a single + * receive for the whole fd batch rather than one per fd). + */ + assert(nb_fd == 1); + for (i = 0; i < nb_fd; i++) { - memset(&msg, 0, sizeof(msg)); + struct msghdr msg = { 0 }; /* Prepare to receive the structures */ iov[0].iov_base = &lkm; @@ -631,12 +638,13 @@ static int kconsumerd_consumerd_recv_fd(int sfd, kconsumerd_send_error(KCONSUMERD_ERROR_RECV_FD); goto end; } + /* if we received fds */ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { switch (cmd_type) { case ADD_STREAM: - DBG("kconsumerd_add_fd %s (%d)", lkm.path_name, (CMSG_DATA(cmsg)[0])); - ret = kconsumerd_add_fd(&lkm, (CMSG_DATA(cmsg)[0])); + DBG("kconsumerd_add_fd %s (%d)", lkm.path_name, ((int *) CMSG_DATA(cmsg))[0]); + ret = kconsumerd_add_fd(&lkm, ((int *) CMSG_DATA(cmsg))[0]); if (ret < 0) { kconsumerd_send_error(KCONSUMERD_OUTFD_ERROR); goto end; diff --git a/liblttsessiondcomm/liblttsessiondcomm.c b/liblttsessiondcomm/liblttsessiondcomm.c index 8fadccf1b..253e63545 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.c +++ b/liblttsessiondcomm/liblttsessiondcomm.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "liblttsessiondcomm.h" @@ -223,12 +224,10 @@ int lttcomm_listen_unix_sock(int sock) */ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) { - struct msghdr msg; + struct msghdr msg = { 0 }; struct iovec iov[1]; ssize_t ret = -1; - memset(&msg, 0, sizeof(msg)); - iov[0].iov_base = buf; iov[0].iov_len = len; msg.msg_iov = iov; @@ -250,12 +249,10 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) */ ssize_t lttcomm_send_unix_sock(int sock, void *buf, size_t len) { - struct msghdr msg; + struct msghdr msg = { 0 }; struct iovec iov[1]; ssize_t ret = -1; - memset(&msg, 0, sizeof(msg)); - iov[0].iov_base = buf; iov[0].iov_len = len; msg.msg_iov = iov; @@ -294,23 +291,29 @@ int lttcomm_close_unix_sock(int sock) */ ssize_t lttcomm_send_fds_unix_sock(int sock, void *buf, int *fds, size_t nb_fd, size_t len) { - struct msghdr msg; + struct msghdr msg = { 0 }; struct cmsghdr *cmptr; struct iovec iov[1]; ssize_t ret = -1; unsigned int sizeof_fds = nb_fd * sizeof(int); char tmp[CMSG_SPACE(sizeof_fds)]; - memset(&msg, 0, sizeof(msg)); + /* + * Note: the consumerd receiver only supports receiving one FD at a + * time for now. + */ + assert(nb_fd == 1); msg.msg_control = (caddr_t)tmp; msg.msg_controllen = CMSG_LEN(sizeof_fds); cmptr = CMSG_FIRSTHDR(&msg); - cmptr->cmsg_len = CMSG_LEN(sizeof_fds); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; + cmptr->cmsg_len = CMSG_LEN(sizeof_fds); memcpy(CMSG_DATA(cmptr), fds, sizeof_fds); + /* Sum of the length of all control messages in the buffer: */ + msg.msg_controllen = cmptr->cmsg_len; iov[0].iov_base = buf; iov[0].iov_len = len;