The branch, master has been updated via bb4dd1f src: Handle stale fds in dup() and dup2(). via 9c03935 src: Add timerfd_create() to handle stale fds. via f850820 src: Add eventfd() to handle stale fds. via dc00232 src: Add signalfd() to handle stale fds. via 95520f6 src: Add socketpair() to handle stale fds. via ea45102 src: Add pipe() to handle stale fds. via 0627527 src: Check for stale fds in swrap_accept(). via 5acfcfe src: Check for stale fds in swrap_socket(). via 05cb607 src: Handle stale fds in swrap_recvmsg_after(). via 3ab00f5 src: Handle stale fds in swrap_sendmsg_after(). via de94be7 src: Try to recover when reading from a fd returns ENOTSOCK. via 27b2055 src: Try to recover when writing to fd returns ENOTSOCK. via 1462a69 src: Try to recover when sockets are closed elsewhere. via 019e4f3 src: Use swrap_recvmsg_(before|after) for swrap_readv(). via e200ed8 Update TODO. via 553d8a2 Update ChangeLog. from bede01d Update TODO.
http://gitweb.samba.org/?p=socket_wrapper.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit bb4dd1f1733fe80493e3f165f206df675fb32beb Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 14:10:53 2014 +0100 src: Handle stale fds in dup() and dup2(). Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 9c03935fc0abb033a32683f5e9d8bd6b2136b8fd Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 13:48:52 2014 +0100 src: Add timerfd_create() to handle stale fds. Reviewed-by: Stefan Metzmacher <me...@samba.org> commit f8508200e90048523fc7c78467dc8e565744f7f9 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 13:42:38 2014 +0100 src: Add eventfd() to handle stale fds. Reviewed-by: Stefan Metzmacher <me...@samba.org> commit dc0023293292d5247a5984e78fc10de9399da5f5 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 13:33:23 2014 +0100 src: Add signalfd() to handle stale fds. Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 95520f672f3cbf311b503d61e2ac9e2a22d209e9 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 13:20:20 2014 +0100 src: Add socketpair() to handle stale fds. Reviewed-by: Stefan Metzmacher <me...@samba.org> commit ea45102993c0800a8a62137da09dbb2787834ed4 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 13:15:34 2014 +0100 src: Add pipe() to handle stale fds. Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 0627527da3abbafdb6f171dbdbc3b719a96a2b62 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 13:10:01 2014 +0100 src: Check for stale fds in swrap_accept(). Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 5acfcfea50ce2dd1b0388c33c849ce19007cf77b Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 10:33:36 2014 +0100 src: Check for stale fds in swrap_socket(). Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 05cb607f08321b1680e51cb3bb33222922f46401 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 11:34:03 2014 +0100 src: Handle stale fds in swrap_recvmsg_after(). Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 3ab00f5deaefa2dbdac9ba71841e178a78988dd2 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 11:30:20 2014 +0100 src: Handle stale fds in swrap_sendmsg_after(). Reviewed-by: Stefan Metzmacher <me...@samba.org> commit de94be7e4b83283f3b46320706fef19b8203b52c Author: Nalin Dahyabhai <na...@dahyabhai.net> Date: Tue Jan 28 11:25:40 2014 +0100 src: Try to recover when reading from a fd returns ENOTSOCK. When attempting to read from a descriptor, if an underlying autobind fails because it's not a socket, stop intercepting uses of that descriptor. Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 27b2055291caf67c6a23e829f596cc6751ce5aad Author: Nalin Dahyabhai <na...@dahyabhai.net> Date: Tue Jan 28 11:24:27 2014 +0100 src: Try to recover when writing to fd returns ENOTSOCK. When attempting to write to a descriptor, if an underlying autobind fails because it's not a socket, stop intercepting uses of that descriptor. Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 1462a69c0a96605081f9f1c0dc5bb54aa98aa202 Author: Nalin Dahyabhai <na...@dahyabhai.net> Date: Tue Jan 28 11:22:26 2014 +0100 src: Try to recover when sockets are closed elsewhere. There are methods for closing descriptors (libc-internal code paths, direct syscalls) which close descriptors in ways that we can't intercept, so try to recover when we notice that that's happened: * If we see a descriptor being handed back from open() that we thought was a socket, stop intercepting uses of that descriptor. Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 019e4f3bb6e5589ad8fe0ca0c07b197cb8cbb677 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 10:06:18 2014 +0100 src: Use swrap_recvmsg_(before|after) for swrap_readv(). Reviewed-by: Stefan Metzmacher <me...@samba.org> commit e200ed88dbf6c9969daee83f9fcdca2c5bd1c0e7 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 10:14:08 2014 +0100 Update TODO. Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 553d8a25f86db7935617fdf4326ac9859d5ebb31 Author: Andreas Schneider <a...@samba.org> Date: Tue Jan 28 10:14:17 2014 +0100 Update ChangeLog. Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: ChangeLog | 5 + ConfigureChecks.cmake | 13 +- TODO | 3 + config.h.cmake | 7 + src/socket_wrapper.c | 448 +++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 385 insertions(+), 91 deletions(-) Changeset truncated at 500 lines: diff --git a/ChangeLog b/ChangeLog index e69de29..d2f5d4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -0,0 +1,5 @@ +ChangeLog +========== + +version 1.0.0 (released 2014-02-02) + * Initial release diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 2d8e690..c05cbb9 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -48,18 +48,17 @@ endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) # HEADERS check_include_file(sys/filio.h HAVE_SYS_FILIO_H) +check_include_file(sys/signalfd.h HAVE_SYS_SIGNALFD_H) +check_include_file(sys/eventfd.h HAVE_SYS_EVENTFD_H) +check_include_file(sys/timerfd.h HAVE_SYS_TIMERFD_H) # FUNCTIONS check_function_exists(strncpy HAVE_STRNCPY) check_function_exists(vsnprintf HAVE_VSNPRINTF) check_function_exists(snprintf HAVE_SNPRINTF) - -if (WIN32) - check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S) - check_function_exists(_vsnprintf HAVE__VSNPRINTF) - check_function_exists(_snprintf HAVE__SNPRINTF) - check_function_exists(_snprintf_s HAVE__SNPRINTF_S) -endif (WIN32) +check_function_exists(signalfd HAVE_SIGNALFD) +check_function_exists(eventfd HAVE_EVENTFD) +check_function_exists(timerfd_create HAVE_TIMERFD_CREATE) if (UNIX) if (NOT LINUX) diff --git a/TODO b/TODO index 2ce46ff..205cfaf 100644 --- a/TODO +++ b/TODO @@ -10,6 +10,8 @@ Library: We accept a connection from a client and need to pass the fd to another child we forked. socket_wrapper then needs to send the 'struct socket_info' to the child first and set it up there. + Or do it like swrap_accept() and call getpeername() and getsockname(). +* Add support for threading. Testing: --------- @@ -17,3 +19,4 @@ Testing: * Add a test for sento() to broadcast 255.255.255.255. * Add a test to check that read/readv/send/ only work on connected sockets. * Add unit tests for conversion functions like convert_in_un_remote(). +* Add threaded tests. diff --git a/config.h.cmake b/config.h.cmake index 63bbdb4..abbf133 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -15,6 +15,9 @@ /************************** HEADER FILES *************************/ #cmakedefine HAVE_SYS_FILIO_H 1 +#cmakedefine HAVE_SYS_SIGNALFD_H 1 +#cmakedefine HAVE_SYS_EVENTFD_H 1 +#cmakedefine HAVE_SYS_TIMERFD_H 1 /************************ STRUCT MEMBERS *************************/ @@ -25,6 +28,10 @@ /* Define to 1 if you have the `getaddrinfo' function. */ #cmakedefine HAVE_GETADDRINFO 1 +#cmakedefine HAVE_SIGNALFD 1 +#cmakedefine HAVE_EVENTFD 1 +#cmakedefine HAVE_TIMERFD_CREATE 1 + #cmakedefine HAVE_ACCEPT_PSOCKLEN_T 1 #cmakedefine HAVE_IOCTL_INT 1 diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 2ea35a9..353a9a5 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -50,6 +50,15 @@ #ifdef HAVE_SYS_FILIO_H #include <sys/filio.h> #endif +#ifdef HAVE_SYS_SIGNALFD_H +#include <sys/signalfd.h> +#endif +#ifdef HAVE_SYS_EVENTFD_H +#include <sys/eventfd.h> +#endif +#ifdef HAVE_SYS_TIMERFD_H +#include <sys/timerfd.h> +#endif #include <sys/uio.h> #include <errno.h> #include <sys/un.h> @@ -283,6 +292,9 @@ struct swrap_libc_fns { socklen_t addrlen); int (*libc_dup)(int fd); int (*libc_dup2)(int oldfd, int newfd); +#ifdef HAVE_EVENTFD + int (*libc_eventfd)(int count, int flags); +#endif int (*libc_getpeername)(int sockfd, struct sockaddr *addr, socklen_t *addrlen); @@ -296,6 +308,8 @@ struct swrap_libc_fns { socklen_t *optlen); int (*libc_ioctl)(int d, unsigned long int request, ...); int (*libc_listen)(int sockfd, int backlog); + int (*libc_open)(const char *pathname, int flags, mode_t mode); + int (*libc_pipe)(int pipefd[2]); int (*libc_read)(int fd, void *buf, size_t count); ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt); int (*libc_recv)(int sockfd, void *buf, size_t len, int flags); @@ -319,7 +333,14 @@ struct swrap_libc_fns { int optname, const void *optval, socklen_t optlen); +#ifdef HAVE_SIGNALFD + int (*libc_signalfd)(int fd, const sigset_t *mask, int flags); +#endif int (*libc_socket)(int domain, int type, int protocol); + int (*libc_socketpair)(int domain, int type, int protocol, int sv[2]); +#ifdef HAVE_TIMERFD_CREATE + int (*libc_timerfd_create)(int clockid, int flags); +#endif ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt); }; @@ -505,6 +526,15 @@ static int libc_dup2(int oldfd, int newfd) return swrap.fns.libc_dup2(oldfd, newfd); } +#ifdef HAVE_EVENTFD +static int libc_eventfd(int count, int flags) +{ + swrap_load_lib_function(SWRAP_LIBC, eventfd); + + return swrap.fns.libc_eventfd(count, flags); +} +#endif + static int libc_getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) @@ -563,6 +593,20 @@ static int libc_listen(int sockfd, int backlog) return swrap.fns.libc_listen(sockfd, backlog); } +static int libc_open(const char *pathname, int flags, mode_t mode) +{ + swrap_load_lib_function(SWRAP_LIBC, open); + + return swrap.fns.libc_open(pathname, flags, mode); +} + +static int libc_pipe(int pipefd[2]) +{ + swrap_load_lib_function(SWRAP_LIBSOCKET, pipe); + + return swrap.fns.libc_pipe(pipefd); +} + static int libc_read(int fd, void *buf, size_t count) { swrap_load_lib_function(SWRAP_LIBC, read); @@ -640,6 +684,15 @@ static int libc_setsockopt(int sockfd, return swrap.fns.libc_setsockopt(sockfd, level, optname, optval, optlen); } +#ifdef HAVE_SIGNALFD +static int libc_signalfd(int fd, const sigset_t *mask, int flags) +{ + swrap_load_lib_function(SWRAP_LIBSOCKET, signalfd); + + return swrap.fns.libc_signalfd(fd, mask, flags); +} +#endif + static int libc_socket(int domain, int type, int protocol) { swrap_load_lib_function(SWRAP_LIBSOCKET, socket); @@ -647,6 +700,22 @@ static int libc_socket(int domain, int type, int protocol) return swrap.fns.libc_socket(domain, type, protocol); } +static int libc_socketpair(int domain, int type, int protocol, int sv[2]) +{ + swrap_load_lib_function(SWRAP_LIBSOCKET, socketpair); + + return swrap.fns.libc_socketpair(domain, type, protocol, sv); +} + +#ifdef HAVE_TIMERFD_CREATE +static int libc_timerfd_create(int clockid, int flags) +{ + swrap_load_lib_function(SWRAP_LIBC, timerfd_create); + + return swrap.fns.libc_timerfd_create(clockid, flags); +} +#endif + static ssize_t libc_writev(int fd, const struct iovec *iov, int iovcnt) { swrap_load_lib_function(SWRAP_LIBSOCKET, writev); @@ -1095,6 +1164,27 @@ static struct socket_info *find_socket_info(int fd) return NULL; } +static void swrap_remove_stale(int fd) +{ + struct socket_info *si = find_socket_info(fd); + struct socket_info_fd *fi; + + if (si != NULL) { + for (fi = si->fds; fi; fi = fi->next) { + if (fi->fd == fd) { + SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd); + SWRAP_DLIST_REMOVE(si->fds, fi); + free(fi); + break; + } + } + + if (si->fds == NULL) { + SWRAP_DLIST_REMOVE(sockets, si); + } + } +} + static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, @@ -1921,6 +2011,29 @@ static void swrap_dump_packet(struct socket_info *si, } /**************************************************************************** + * SIGNALFD + ***************************************************************************/ + +#ifdef HAVE_SIGNALFD +static int swrap_signalfd(int fd, const sigset_t *mask, int flags) +{ + int rc; + + rc = libc_signalfd(fd, mask, flags); + if (rc != -1) { + swrap_remove_stale(fd); + } + + return rc; +} + +int signalfd(int fd, const sigset_t *mask, int flags) +{ + return swrap_signalfd(fd, mask, flags); +} +#endif + +/**************************************************************************** * SOCKET ***************************************************************************/ @@ -1994,7 +2107,15 @@ static int swrap_socket(int family, int type, int protocol) */ fd = libc_socket(AF_UNIX, type, 0); - if (fd == -1) return -1; + if (fd == -1) { + return -1; + } + + /* Check if we have a stale fd and remove it */ + si = find_socket_info(fd); + if (si != NULL) { + swrap_remove_stale(fd); + } si = (struct socket_info *)malloc(sizeof(struct socket_info)); memset(si, 0, sizeof(struct socket_info)); @@ -2031,6 +2152,73 @@ int socket(int family, int type, int protocol) } /**************************************************************************** + * SOCKETPAIR + ***************************************************************************/ + +static int swrap_socketpair(int family, int type, int protocol, int sv[2]) +{ + int rc; + + rc = libc_socketpair(family, type, protocol, sv); + if (rc != -1) { + swrap_remove_stale(sv[0]); + swrap_remove_stale(sv[1]); + } + + return rc; +} + +int socketpair(int family, int type, int protocol, int sv[2]) +{ + return swrap_socketpair(family, type, protocol, sv); +} + +/**************************************************************************** + * SOCKETPAIR + ***************************************************************************/ + +#ifdef HAVE_TIMERFD_CREATE +static int swrap_timerfd_create(int clockid, int flags) +{ + int fd; + + fd = libc_timerfd_create(clockid, flags); + if (fd != -1) { + swrap_remove_stale(fd); + } + + return fd; +} + +int timerfd_create(int clockid, int flags) +{ + return swrap_timerfd_create(clockid, flags); +} +#endif + +/**************************************************************************** + * PIPE + ***************************************************************************/ + +static int swrap_pipe(int pipefd[2]) +{ + int rc; + + rc = libc_pipe(pipefd); + if (rc != -1) { + swrap_remove_stale(pipefd[0]); + swrap_remove_stale(pipefd[1]); + } + + return rc; +} + +int pipe(int pipefd[2]) +{ + return swrap_pipe(pipefd); +} + +/**************************************************************************** * ACCEPT ***************************************************************************/ @@ -2072,6 +2260,10 @@ static int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) ret = libc_accept(s, (struct sockaddr *)(void *)&un_addr, &un_addrlen); if (ret == -1) { + if (errno == ENOTSOCK) { + /* Remove stale fds */ + swrap_remove_stale(s); + } free(my_addr); return ret; } @@ -2435,6 +2627,38 @@ int listen(int s, int backlog) } /**************************************************************************** + * OPEN + ***************************************************************************/ + +static int swrap_open(const char *pathname, int flags, mode_t mode) +{ + int ret; + + ret = libc_open(pathname, flags, mode); + if (ret != -1) { + /* + * There are methods for closing descriptors (libc-internal code + * paths, direct syscalls) which close descriptors in ways that + * we can't intercept, so try to recover when we notice that + * that's happened + */ + swrap_remove_stale(ret); + } + return ret; +} + +int open(const char *pathname, int flags, ...) +{ + mode_t mode; + va_list ap; + + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + return swrap_open(pathname, flags, mode); +} + +/**************************************************************************** * GETPEERNAME ***************************************************************************/ @@ -2711,7 +2935,15 @@ static ssize_t swrap_sendmsg_before(int fd, if (si->bound == 0) { ret = swrap_auto_bind(fd, si, si->family); - if (ret == -1) return -1; + if (ret == -1) { + if (errno == ENOTSOCK) { + swrap_remove_stale(fd); + return -ENOTSOCK; + } else { + SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_sendmsg_before failed"); + return -1; + } + } } if (!si->defer_connect) { @@ -2745,7 +2977,8 @@ static ssize_t swrap_sendmsg_before(int fd, return 0; } -static void swrap_sendmsg_after(struct socket_info *si, +static void swrap_sendmsg_after(int fd, + struct socket_info *si, struct msghdr *msg, const struct sockaddr *to, ssize_t ret) @@ -2758,8 +2991,13 @@ static void swrap_sendmsg_after(struct socket_info *si, size_t remain; /* to give better errors */ - if (ret == -1 && saved_errno == ENOENT) { - saved_errno = EHOSTUNREACH; + if (ret == -1) { + if (saved_errno == ENOENT) { + saved_errno = EHOSTUNREACH; + } else if (saved_errno == ENOTSOCK) { + /* If the fd is not a socket, remove it */ + swrap_remove_stale(fd); + } } for (i = 0; i < (size_t)msg->msg_iovlen; i++) { @@ -2867,7 +3105,20 @@ static int swrap_recvmsg_before(int fd, if (si->bound == 0) { ret = swrap_auto_bind(fd, si, si->family); if (ret == -1) { - return -1; + /* + * When attempting to read or write to a + * descriptor, if an underlying autobind fails + * because it's not a socket, stop intercepting + * uses of that descriptor. + */ + if (errno == ENOTSOCK) { + swrap_remove_stale(fd); + return -ENOTSOCK; + } else { + SWRAP_LOG(SWRAP_LOG_ERROR, + "swrap_recvmsg_before failed"); + return -1; + } } } break; @@ -2879,7 +3130,8 @@ static int swrap_recvmsg_before(int fd, return 0; } -static int swrap_recvmsg_after(struct socket_info *si, +static int swrap_recvmsg_after(int fd, + struct socket_info *si, struct msghdr *msg, const struct sockaddr_un *un_addr, socklen_t un_addrlen, @@ -2893,8 +3145,13 @@ static int swrap_recvmsg_after(struct socket_info *si, size_t remain; /* to give better errors */ - if (ret == -1 && saved_errno == ENOENT) { - saved_errno = EHOSTUNREACH; + if (ret == -1) { + if (saved_errno == ENOENT) { + saved_errno = EHOSTUNREACH; + } else if (saved_errno == ENOTSOCK) { + /* If the fd is not a socket, remove it */ + swrap_remove_stale(fd); + } } -- Socket Wrapper Repository