X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Funix.c;h=023bff847273df004c537593cbbbceb012540681;hb=bf8ac2eaec39ba99aaac4de946bbaf3dca4f5539;hp=6cdc759965ccacd7ef515ba3f4cc5fe87386d9e0;hpb=b72ce6309a63e5c2ec29042c4677ba559f21746b;p=lttng-tools.git diff --git a/src/common/unix.c b/src/common/unix.c index 6cdc75996..023bff847 100644 --- a/src/common/unix.c +++ b/src/common/unix.c @@ -15,10 +15,11 @@ #include #include #include -#include #include +#include #include +#include #include "unix.h" @@ -180,6 +181,10 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) ssize_t ret = -1; size_t len_last; + assert(sock); + assert(buf); + assert(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = buf; @@ -222,6 +227,10 @@ ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len) struct iovec iov[1]; ssize_t ret; + assert(sock); + assert(buf); + assert(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = buf; @@ -253,7 +262,7 @@ retry: goto end; } } - ret = len; + end: return ret; } @@ -270,6 +279,10 @@ ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len) struct iovec iov[1]; ssize_t ret; + assert(sock); + assert(buf); + assert(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = (void *) buf; @@ -320,6 +333,10 @@ ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len) struct iovec iov[1]; ssize_t ret; + assert(sock); + assert(buf); + assert(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = (void *) buf; @@ -352,7 +369,6 @@ retry: goto end; } } - ret = len; end: return ret; } @@ -395,6 +411,10 @@ ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd) char tmp[CMSG_SPACE(sizeof_fds)]; char dummy = 0; + assert(sock); + assert(fds); + assert(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); memset(tmp, 0, sizeof(tmp)); @@ -436,6 +456,78 @@ ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd) return ret; } +/* + * Send the fd(s) of a payload view over a unix socket. + * + * Returns the size of data sent, or negative error value. + */ +static +ssize_t _lttcomm_send_payload_view_fds_unix_sock(int sock, + struct lttng_payload_view *view, + bool blocking) +{ + int i; + ssize_t ret; + struct lttng_dynamic_array raw_fds; + const int fd_count = lttng_payload_view_get_fd_handle_count(view); + + lttng_dynamic_array_init(&raw_fds, sizeof(int), NULL); + + if (fd_count < 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + /* + * Prepare a contiguous array of file descriptors to send them. + * + * Note that the reference to each fd is released during the iteration; + * we're just getting the numerical value of the fds to conform to the + * syscall's interface. We rely on the fact that "view" must remain + * valid for the duration of the call and that the underlying payload + * owns a reference to the fd_handles. + */ + for (i = 0; i < fd_count; i++) { + struct fd_handle *handle = + lttng_payload_view_pop_fd_handle(view); + const int raw_fd = fd_handle_get_fd(handle); + const int add_ret = lttng_dynamic_array_add_element( + &raw_fds, &raw_fd); + + fd_handle_put(handle); + if (add_ret) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + } + + if (blocking) { + ret = lttcomm_send_fds_unix_sock(sock, + (const int *) raw_fds.buffer.data, fd_count); + } else { + ret = lttcomm_send_fds_unix_sock_non_block(sock, + (const int *) raw_fds.buffer.data, fd_count); + } + +end: + lttng_dynamic_array_reset(&raw_fds); + return ret; +} + +LTTNG_HIDDEN +ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock, + struct lttng_payload_view *view) +{ + return _lttcomm_send_payload_view_fds_unix_sock(sock, view, true); +} + +LTTNG_HIDDEN +ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock, + struct lttng_payload_view *view) +{ + return _lttcomm_send_payload_view_fds_unix_sock(sock, view, false); +} + /* * Send a message accompanied by fd(s) over a unix socket. * Only use for non blocking socket. @@ -453,6 +545,10 @@ ssize_t lttcomm_send_fds_unix_sock_non_block(int sock, const int *fds, size_t nb char tmp[CMSG_SPACE(sizeof_fds)]; char dummy = 0; + assert(sock); + assert(fds); + assert(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); memset(tmp, 0, sizeof(tmp)); @@ -542,6 +638,10 @@ ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) struct msghdr msg; char dummy; + assert(sock); + assert(fds); + assert(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); /* Prepare to receive the structures */ @@ -630,6 +730,117 @@ end: return ret; } +static +void close_raw_fd(void *ptr) +{ + const int raw_fd = *((const int *) ptr); + + if (raw_fd >= 0) { + const int ret = close(raw_fd); + + if (ret) { + PERROR("Failed to close file descriptor %d", raw_fd); + } + } +} + +static +enum lttng_error_code add_fds_to_payload(struct lttng_dynamic_array *raw_fds, + struct lttng_payload *payload) +{ + int i; + enum lttng_error_code ret_code = LTTNG_OK; + const int fd_count = lttng_dynamic_array_get_count(raw_fds); + + for (i = 0; i < fd_count; i++) { + int ret; + struct fd_handle *handle; + int *raw_fd = (int *) lttng_dynamic_array_get_element( + raw_fds, i); + + assert(*raw_fd != -1); + + handle = fd_handle_create(*raw_fd); + if (!handle) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + /* FD ownership transferred to the handle. */ + *raw_fd = -1; + + ret = lttng_payload_push_fd_handle(payload, handle); + fd_handle_put(handle); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + } + +end: + return ret_code; +} + +static +ssize_t _lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd, + struct lttng_payload *payload, bool blocking) +{ + int i = 0; + enum lttng_error_code add_ret; + ssize_t ret; + int default_value = -1; + struct lttng_dynamic_array raw_fds; + + assert(sock); + assert(payload); + assert(nb_fd > 0); + + lttng_dynamic_array_init(&raw_fds, sizeof(int), close_raw_fd); + + for (i = 0; i < nb_fd; i++) { + if (lttng_dynamic_array_add_element(&raw_fds, &default_value)) { + ret = -LTTNG_ERR_NOMEM; + goto end; + } + } + + if (blocking) { + ret = lttcomm_recv_fds_unix_sock( + sock, (int *) raw_fds.buffer.data, nb_fd); + } else { + ret = lttcomm_recv_fds_unix_sock_non_block( + sock, (int *) raw_fds.buffer.data, nb_fd); + } + + if (ret <= 0) { + goto end; + } + + add_ret = add_fds_to_payload(&raw_fds, payload); + if (add_ret != LTTNG_OK) { + ret = - (int) add_ret; + goto end; + } + +end: + lttng_dynamic_array_reset(&raw_fds); + return ret; +} + +LTTNG_HIDDEN +ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd, + struct lttng_payload *payload) +{ + return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, true); +} + +LTTNG_HIDDEN +ssize_t lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd, + struct lttng_payload *payload) +{ + return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, false); +} + /* * Recv a message accompanied by fd(s) from a non-blocking unix socket. * Only use with non-blocking sockets. @@ -650,6 +861,10 @@ ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd) struct cmsghdr *cmsg; size_t sizeof_fds = nb_fd * sizeof(int); + assert(sock); + assert(fds); + assert(nb_fd > 0); + #ifdef __linux__ /* Account for the struct ucred cmsg in the buffer size */ #define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred)) @@ -772,7 +987,7 @@ end: * Returns the size of data sent, or negative error value. */ LTTNG_HIDDEN -ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len) +ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; @@ -788,7 +1003,11 @@ ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len) memset(&msg, 0, sizeof(msg)); - iov[0].iov_base = buf; + assert(sock); + assert(buf); + assert(len > 0); + + iov[0].iov_base = (void *) buf; iov[0].iov_len = len; msg.msg_iov = iov; msg.msg_iovlen = 1; @@ -846,13 +1065,12 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, char anc_buf[CMSG_SPACE(sizeof_cred)]; #endif /* __linux__ */ - memset(&msg, 0, sizeof(msg)); + assert(sock); + assert(buf); + assert(len > 0); + assert(creds); - /* Not allowed */ - if (creds == NULL) { - ret = -1; - goto end; - } + memset(&msg, 0, sizeof(msg)); /* Prepare to receive the structures */ iov[0].iov_base = buf;