X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Funix.c;h=9918db2e683e18f9e880e1025779057bb1289456;hb=3afa94aeca5a0daae40fd7b6cc96b7e4c150c7d8;hp=0409750c3ff7ada10465c1d1ee92d878afb3309a;hpb=5b86bd5e6c2e05f3a6296fd569d824f03d5e7857;p=lttng-tools.git diff --git a/src/common/unix.c b/src/common/unix.c index 0409750c3..9918db2e6 100644 --- a/src/common/unix.c +++ b/src/common/unix.c @@ -7,7 +7,6 @@ */ #define _LGPL_SOURCE -#include #include #include #include @@ -15,17 +14,17 @@ #include #include #include -#include #include +#include #include +#include #include "unix.h" /* * Connect to unix socket using the path name. */ -LTTNG_HIDDEN int lttcomm_connect_unix_sock(const char *pathname) { struct sockaddr_un s_un; @@ -75,7 +74,6 @@ error: * Do an accept(2) on the sock and return the new file descriptor. The socket * MUST be bind(2) before. */ -LTTNG_HIDDEN int lttcomm_accept_unix_sock(int sock) { int new_fd; @@ -91,7 +89,6 @@ int lttcomm_accept_unix_sock(int sock) return new_fd; } -LTTNG_HIDDEN int lttcomm_create_anon_unix_socketpair(int *fds) { if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds) < 0) { @@ -105,7 +102,6 @@ int lttcomm_create_anon_unix_socketpair(int *fds) * Creates a AF_UNIX local socket using pathname bind the socket upon creation * and return the fd. */ -LTTNG_HIDDEN int lttcomm_create_unix_sock(const char *pathname) { struct sockaddr_un s_un; @@ -153,7 +149,6 @@ error: /* * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN. */ -LTTNG_HIDDEN int lttcomm_listen_unix_sock(int sock) { int ret; @@ -172,7 +167,6 @@ int lttcomm_listen_unix_sock(int sock) * * Return the size of received data. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) { struct msghdr msg; @@ -180,6 +174,10 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) ssize_t ret = -1; size_t len_last; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = buf; @@ -193,7 +191,7 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) if (ret > 0) { iov[0].iov_base += ret; iov[0].iov_len -= ret; - assert(ret <= len_last); + LTTNG_ASSERT(ret <= len_last); } } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR)); if (ret < 0) { @@ -215,13 +213,16 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len) * * Return the size of received data. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; ssize_t ret; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = buf; @@ -263,13 +264,16 @@ end: * * Return the size of sent data. */ -LTTNG_HIDDEN ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; ssize_t ret; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = (void *) buf; @@ -313,13 +317,16 @@ end: * * Return the size of sent data. */ -LTTNG_HIDDEN ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len) { struct msghdr msg; struct iovec iov[1]; ssize_t ret; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + memset(&msg, 0, sizeof(msg)); iov[0].iov_base = (void *) buf; @@ -359,7 +366,6 @@ end: /* * Shutdown cleanly a unix socket. */ -LTTNG_HIDDEN int lttcomm_close_unix_sock(int sock) { int ret, closeret; @@ -383,7 +389,6 @@ int lttcomm_close_unix_sock(int sock) * * Returns the size of data sent, or negative error value. */ -LTTNG_HIDDEN ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd) { struct msghdr msg; @@ -394,6 +399,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; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_ASSERT(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); memset(tmp, 0, sizeof(tmp)); @@ -435,13 +444,82 @@ 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; +} + +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); +} + +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. * * Returns the size of data sent, or negative error value. */ -LTTNG_HIDDEN ssize_t lttcomm_send_fds_unix_sock_non_block(int sock, const int *fds, size_t nb_fd) { struct msghdr msg; @@ -452,6 +530,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; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_ASSERT(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); memset(tmp, 0, sizeof(tmp)); @@ -522,7 +604,6 @@ end: * Expect at most "nb_fd" file descriptors. Returns the number of fd * actually received in nb_fd. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) { struct iovec iov[1]; @@ -541,6 +622,10 @@ ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd) struct msghdr msg; char dummy; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_ASSERT(nb_fd > 0); + memset(&msg, 0, sizeof(msg)); /* Prepare to receive the structures */ @@ -629,6 +714,115 @@ 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); + + LTTNG_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; + + LTTNG_ASSERT(sock); + LTTNG_ASSERT(payload); + LTTNG_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; +} + +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); +} + +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. @@ -641,7 +835,6 @@ end: * possible since the FDs are actually in the control message. It is all or * nothing, still the sender side can send the wrong number of fds. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd) { struct iovec iov[1]; @@ -649,6 +842,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); + LTTNG_ASSERT(sock); + LTTNG_ASSERT(fds); + LTTNG_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)) @@ -770,29 +967,32 @@ 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]; ssize_t ret = -1; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) struct cmsghdr *cmptr; size_t sizeof_cred = sizeof(lttng_sock_cred); char anc_buf[CMSG_SPACE(sizeof_cred)]; lttng_sock_cred *creds; memset(anc_buf, 0, CMSG_SPACE(sizeof_cred) * sizeof(char)); -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ memset(&msg, 0, sizeof(msg)); - iov[0].iov_base = buf; + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + + iov[0].iov_base = (void *) buf; iov[0].iov_len = len; msg.msg_iov = iov; msg.msg_iovlen = 1; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) msg.msg_control = (caddr_t) anc_buf; msg.msg_controllen = CMSG_LEN(sizeof_cred); @@ -809,7 +1009,7 @@ ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len) LTTNG_SOCK_SET_UID_CRED(creds, geteuid()); LTTNG_SOCK_SET_GID_CRED(creds, getegid()); LTTNG_SOCK_SET_PID_CRED(creds, getpid()); -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ do { ret = sendmsg(sock, &msg, 0); @@ -831,7 +1031,6 @@ ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len) * * Returns the size of received data, or negative error value. */ -LTTNG_HIDDEN ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, lttng_sock_cred *creds) { @@ -839,19 +1038,18 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, struct iovec iov[1]; ssize_t ret; size_t len_last; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) struct cmsghdr *cmptr; size_t sizeof_cred = sizeof(lttng_sock_cred); char anc_buf[CMSG_SPACE(sizeof_cred)]; -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ - memset(&msg, 0, sizeof(msg)); + LTTNG_ASSERT(sock); + LTTNG_ASSERT(buf); + LTTNG_ASSERT(len > 0); + LTTNG_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; @@ -859,10 +1057,10 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, msg.msg_iov = iov; msg.msg_iovlen = 1; -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) msg.msg_control = anc_buf; msg.msg_controllen = sizeof(anc_buf); -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ do { len_last = iov[0].iov_len; @@ -870,7 +1068,7 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, if (ret > 0) { iov[0].iov_base += ret; iov[0].iov_len -= ret; - assert(ret <= len_last); + LTTNG_ASSERT(ret <= len_last); } } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR)); if (ret < 0) { @@ -881,7 +1079,7 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, } /* Else ret = 0 meaning an orderly shutdown. */ -#ifdef __linux__ +#if defined(__linux__) || defined(__CYGWIN__) if (msg.msg_flags & MSG_CTRUNC) { fprintf(stderr, "Error: Control message truncated.\n"); ret = -1; @@ -910,18 +1108,15 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, } memcpy(creds, CMSG_DATA(cmptr), sizeof_cred); -#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__)) - { - int peer_ret; - - peer_ret = getpeereid(sock, &creds->uid, &creds->gid); - if (peer_ret != 0) { - return peer_ret; - } +#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__)) + if (lttng_get_unix_socket_peer_creds(sock, creds)) { + fprintf(stderr, "ARG\n"); + ret = -1; + goto end; } #else #error "Please implement credential support for your OS." -#endif /* __linux__ */ +#endif /* __linux__, __CYGWIN__ */ end: return ret; @@ -930,8 +1125,7 @@ end: /* * Set socket option to use credentials passing. */ -#ifdef __linux__ -LTTNG_HIDDEN +#if defined(__linux__) || defined(__CYGWIN__) int lttcomm_setsockopt_creds_unix_sock(int sock) { int ret, on = 1; @@ -943,8 +1137,7 @@ int lttcomm_setsockopt_creds_unix_sock(int sock) } return ret; } -#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__)) -LTTNG_HIDDEN +#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__)) int lttcomm_setsockopt_creds_unix_sock(int sock) { return 0;