The branch, master has been updated via d8cf3b0 swrap: Handle threads that fork via c989bbc cmake: Check for constructor attribute via f5cddcd swrap: Make symbol loading thread-safe via 201811d cmake: Link pthread library headers via 3507e18 swrap: Fix strict-aliasing issues while loading symbols from b61f5df tests: Add a test for max_sockets
https://git.samba.org/?p=socket_wrapper.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit d8cf3b0ca8ce24aaf19e4692882dadffa921f763 Author: Andreas Schneider <a...@samba.org> Date: Thu Oct 20 10:37:18 2016 +0200 swrap: Handle threads that fork Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit c989bbc9f6afaad9e4b26501d57d7acb1297d1cb Author: Andreas Schneider <a...@samba.org> Date: Thu Oct 20 10:35:50 2016 +0200 cmake: Check for constructor attribute Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit f5cddcd300b779131662519d56ae90fcebe459e1 Author: Andreas Schneider <a...@samba.org> Date: Thu Oct 20 10:22:40 2016 +0200 swrap: Make symbol loading thread-safe Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> commit 201811dc614a4787482c3bb2fa14f47112a05a34 Author: Michael Adam <ob...@samba.org> Date: Sun Sep 18 20:28:06 2016 +0200 cmake: Link pthread library headers Signed-off-by: Michael Adam <ob...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 3507e186d08fa8170a3499c9e69a49aa60ff9dcd Author: Andreas Schneider <a...@samba.org> Date: Thu Oct 20 10:56:35 2016 +0200 swrap: Fix strict-aliasing issues while loading symbols Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Michael Adam <ob...@samba.org> ----------------------------------------------------------------------- Summary of changes: ConfigureChecks.cmake | 12 ++ config.h.cmake | 1 + src/CMakeLists.txt | 2 +- src/socket_wrapper.c | 434 +++++++++++++++++++++++++++++++++----------------- tests/CMakeLists.txt | 3 +- 5 files changed, 306 insertions(+), 146 deletions(-) Changeset truncated at 500 lines: diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 48455ef..71b34ce 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -172,6 +172,18 @@ int main(void) { }" HAVE_SOCKADDR_STORAGE) check_c_source_compiles(" +void test_constructor_attribute(void) __attribute__ ((constructor)); + +void test_constructor_attribute(void) +{ + return; +} + +int main(void) { + return 0; +}" HAVE_CONSTRUCTOR_ATTRIBUTE) + +check_c_source_compiles(" void test_destructor_attribute(void) __attribute__ ((destructor)); void test_destructor_attribute(void) diff --git a/config.h.cmake b/config.h.cmake index a9b8ce8..6786b8a 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -58,6 +58,7 @@ /**************************** OPTIONS ****************************/ #cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1 +#cmakedefine HAVE_CONSTRUCTOR_ATTRIBUTE 1 #cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1 #cmakedefine HAVE_ADDRESS_SANITIZER_ATTRIBUTE 1 #cmakedefine HAVE_SOCKADDR_STORAGE 1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b22d77..3b4d7d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ include_directories(${CMAKE_BINARY_DIR}) add_library(socket_wrapper SHARED socket_wrapper.c) -target_link_libraries(socket_wrapper ${SWRAP_REQUIRED_LIBRARIES}) +target_link_libraries(socket_wrapper ${SWRAP_REQUIRED_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) install( TARGETS diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index 84dfc07..6679d5c 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -79,6 +79,7 @@ #ifdef HAVE_RPC_RPC_H #include <rpc/rpc.h> #endif +#include <pthread.h> enum swrap_dbglvl_e { SWRAP_LOG_ERROR = 0, @@ -94,6 +95,12 @@ enum swrap_dbglvl_e { #define PRINTF_ATTRIBUTE(a,b) #endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */ +#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE +#define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor)) +#else +#define CONSTRUCTOR_ATTRIBUTE +#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ + #ifdef HAVE_DESTRUCTOR_ATTRIBUTE #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor)) #else @@ -152,6 +159,22 @@ enum swrap_dbglvl_e { # endif #endif +/* Macros for accessing mutexes */ +# define SWRAP_LOCK(m) do { \ + pthread_mutex_lock(&(m ## _mutex)); \ +} while(0) + +# define SWRAP_UNLOCK(m) do { \ + pthread_mutex_unlock(&(m ## _mutex)); \ +} while(0) + +/* Add new global locks here please */ +# define SWRAP_LOCK_ALL \ + SWRAP_LOCK(libc_symbol_binding); \ + +# define SWRAP_UNLOCK_ALL \ + SWRAP_UNLOCK(libc_symbol_binding); \ + #define SWRAP_DLIST_ADD(list,item) do { \ if (!(list)) { \ @@ -305,9 +328,14 @@ static size_t max_sockets = 0; */ static struct socket_info_fd *socket_fds; +/* The mutex for accessing the global libc.symbols */ +static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER; + /* Function prototypes */ bool socket_wrapper_enabled(void); + +void swrap_constructor(void) CONSTRUCTOR_ATTRIBUTE; void swrap_destructor(void) DESTRUCTOR_ATTRIBUTE; #ifdef NDEBUG @@ -368,86 +396,133 @@ static void swrap_log(enum swrap_dbglvl_e dbglvl, #include <dlfcn.h> -struct swrap_libc_fns { #ifdef HAVE_ACCEPT4 - int (*libc_accept4)(int sockfd, - struct sockaddr *addr, - socklen_t *addrlen, - int flags); +typedef int (*__libc_accept4)(int sockfd, + struct sockaddr *addr, + socklen_t *addrlen, + int flags); #else - int (*libc_accept)(int sockfd, - struct sockaddr *addr, - socklen_t *addrlen); +typedef int (*__libc_accept)(int sockfd, + struct sockaddr *addr, + socklen_t *addrlen); #endif - int (*libc_bind)(int sockfd, - const struct sockaddr *addr, - socklen_t addrlen); - int (*libc_close)(int fd); - int (*libc_connect)(int sockfd, - const struct sockaddr *addr, - socklen_t addrlen); - int (*libc_dup)(int fd); - int (*libc_dup2)(int oldfd, int newfd); - int (*libc_fcntl)(int fd, int cmd, ...); - FILE *(*libc_fopen)(const char *name, const char *mode); +typedef int (*__libc_bind)(int sockfd, + const struct sockaddr *addr, + socklen_t addrlen); +typedef int (*__libc_close)(int fd); +typedef int (*__libc_connect)(int sockfd, + const struct sockaddr *addr, + socklen_t addrlen); +typedef int (*__libc_dup)(int fd); +typedef int (*__libc_dup2)(int oldfd, int newfd); +typedef int (*__libc_fcntl)(int fd, int cmd, ...); +typedef FILE *(*__libc_fopen)(const char *name, const char *mode); #ifdef HAVE_EVENTFD - int (*libc_eventfd)(int count, int flags); +typedef int (*__libc_eventfd)(int count, int flags); #endif - int (*libc_getpeername)(int sockfd, - struct sockaddr *addr, - socklen_t *addrlen); - int (*libc_getsockname)(int sockfd, - struct sockaddr *addr, - socklen_t *addrlen); - int (*libc_getsockopt)(int sockfd, +typedef int (*__libc_getpeername)(int sockfd, + struct sockaddr *addr, + socklen_t *addrlen); +typedef int (*__libc_getsockname)(int sockfd, + struct sockaddr *addr, + socklen_t *addrlen); +typedef int (*__libc_getsockopt)(int sockfd, int level, int optname, void *optval, 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); - int (*libc_recvfrom)(int sockfd, +typedef int (*__libc_ioctl)(int d, unsigned long int request, ...); +typedef int (*__libc_listen)(int sockfd, int backlog); +typedef int (*__libc_open)(const char *pathname, int flags, mode_t mode); +typedef int (*__libc_pipe)(int pipefd[2]); +typedef int (*__libc_read)(int fd, void *buf, size_t count); +typedef ssize_t (*__libc_readv)(int fd, const struct iovec *iov, int iovcnt); +typedef int (*__libc_recv)(int sockfd, void *buf, size_t len, int flags); +typedef int (*__libc_recvfrom)(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); - int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags); - int (*libc_send)(int sockfd, const void *buf, size_t len, int flags); - int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags); - int (*libc_sendto)(int sockfd, +typedef int (*__libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags); +typedef int (*__libc_send)(int sockfd, const void *buf, size_t len, int flags); +typedef int (*__libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags); +typedef int (*__libc_sendto)(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dst_addr, socklen_t addrlen); - int (*libc_setsockopt)(int sockfd, +typedef int (*__libc_setsockopt)(int sockfd, int level, int optname, const void *optval, socklen_t optlen); #ifdef HAVE_SIGNALFD - int (*libc_signalfd)(int fd, const sigset_t *mask, int flags); +typedef 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]); +typedef int (*__libc_socket)(int domain, int type, int protocol); +typedef int (*__libc_socketpair)(int domain, int type, int protocol, int sv[2]); #ifdef HAVE_TIMERFD_CREATE - int (*libc_timerfd_create)(int clockid, int flags); +typedef int (*__libc_timerfd_create)(int clockid, int flags); #endif - ssize_t (*libc_write)(int fd, const void *buf, size_t count); - ssize_t (*libc_writev)(int fd, const struct iovec *iov, int iovcnt); +typedef ssize_t (*__libc_write)(int fd, const void *buf, size_t count); +typedef ssize_t (*__libc_writev)(int fd, const struct iovec *iov, int iovcnt); + +#define SWRAP_SYMBOL_ENTRY(i) \ + union { \ + __libc_##i f; \ + void *obj; \ + } _libc_##i + +struct swrap_libc_symbols { +#ifdef HAVE_ACCEPT4 + SWRAP_SYMBOL_ENTRY(accept4); +#else + SWRAP_SYMBOL_ENTRY(accept); +#endif + SWRAP_SYMBOL_ENTRY(bind); + SWRAP_SYMBOL_ENTRY(close); + SWRAP_SYMBOL_ENTRY(connect); + SWRAP_SYMBOL_ENTRY(dup); + SWRAP_SYMBOL_ENTRY(dup2); + SWRAP_SYMBOL_ENTRY(fcntl); + SWRAP_SYMBOL_ENTRY(fopen); +#ifdef HAVE_EVENTFD + SWRAP_SYMBOL_ENTRY(eventfd); +#endif + SWRAP_SYMBOL_ENTRY(getpeername); + SWRAP_SYMBOL_ENTRY(getsockname); + SWRAP_SYMBOL_ENTRY(getsockopt); + SWRAP_SYMBOL_ENTRY(ioctl); + SWRAP_SYMBOL_ENTRY(listen); + SWRAP_SYMBOL_ENTRY(open); + SWRAP_SYMBOL_ENTRY(pipe); + SWRAP_SYMBOL_ENTRY(read); + SWRAP_SYMBOL_ENTRY(readv); + SWRAP_SYMBOL_ENTRY(recv); + SWRAP_SYMBOL_ENTRY(recvfrom); + SWRAP_SYMBOL_ENTRY(recvmsg); + SWRAP_SYMBOL_ENTRY(send); + SWRAP_SYMBOL_ENTRY(sendmsg); + SWRAP_SYMBOL_ENTRY(sendto); + SWRAP_SYMBOL_ENTRY(setsockopt); +#ifdef HAVE_SIGNALFD + SWRAP_SYMBOL_ENTRY(signalfd); +#endif + SWRAP_SYMBOL_ENTRY(socket); + SWRAP_SYMBOL_ENTRY(socketpair); + SWRAP_SYMBOL_ENTRY(timerfd_create); + SWRAP_SYMBOL_ENTRY(write); + SWRAP_SYMBOL_ENTRY(writev); }; struct swrap { - void *libc_handle; - void *libsocket_handle; - - struct swrap_libc_fns fns; + struct { + void *handle; + void *socket_handle; + struct swrap_libc_symbols symbols; + } libc; }; static struct swrap swrap; @@ -507,18 +582,18 @@ static void *swrap_load_lib_handle(enum swrap_lib lib) } } - swrap.libsocket_handle = handle; + swrap.libc.socket_handle = handle; } break; #endif /* FALL TROUGH */ case SWRAP_LIBC: - handle = swrap.libc_handle; + handle = swrap.libc.handle; #ifdef LIBC_SO if (handle == NULL) { handle = dlopen(LIBC_SO, flags); - swrap.libc_handle = handle; + swrap.libc.handle = handle; } #endif if (handle == NULL) { @@ -532,14 +607,14 @@ static void *swrap_load_lib_handle(enum swrap_lib lib) } } - swrap.libc_handle = handle; + swrap.libc.handle = handle; } break; } if (handle == NULL) { #ifdef RTLD_NEXT - handle = swrap.libc_handle = swrap.libsocket_handle = RTLD_NEXT; + handle = swrap.libc.handle = swrap.libc.socket_handle = RTLD_NEXT; #else SWRAP_LOG(SWRAP_LOG_ERROR, "Failed to dlopen library: %s\n", @@ -551,7 +626,7 @@ static void *swrap_load_lib_handle(enum swrap_lib lib) return handle; } -static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name) +static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name) { void *handle; void *func; @@ -561,24 +636,43 @@ static void *_swrap_load_lib_function(enum swrap_lib lib, const char *fn_name) func = dlsym(handle, fn_name); if (func == NULL) { SWRAP_LOG(SWRAP_LOG_ERROR, - "Failed to find %s: %s\n", - fn_name, dlerror()); + "Failed to find %s: %s\n", + fn_name, + dlerror()); exit(-1); } SWRAP_LOG(SWRAP_LOG_TRACE, - "Loaded %s from %s", - fn_name, swrap_str_lib(lib)); + "Loaded %s from %s", + fn_name, + swrap_str_lib(lib)); + return func; } -#define swrap_load_lib_function(lib, fn_name) \ - if (swrap.fns.libc_##fn_name == NULL) { \ - void *swrap_cast_ptr = _swrap_load_lib_function(lib, #fn_name); \ - *(void **) (&swrap.fns.libc_##fn_name) = \ - swrap_cast_ptr; \ - } +#define swrap_bind_symbol_libc(sym_name) \ + SWRAP_LOCK(libc_symbol_binding); \ + if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ + swrap.libc.symbols._libc_##sym_name.obj = \ + _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \ + } \ + SWRAP_UNLOCK(libc_symbol_binding) + +#define swrap_bind_symbol_libsocket(sym_name) \ + SWRAP_LOCK(libc_symbol_binding); \ + if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ + swrap.libc.symbols._libc_##sym_name.obj = \ + _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \ + } \ + SWRAP_UNLOCK(libc_symbol_binding) +#define swrap_bind_symbol_libnsl(sym_name) \ + SWRAP_LOCK(libc_symbol_binding); \ + if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \ + swrap.libc.symbols._libc_##sym_name.obj = \ + _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \ + } \ + SWRAP_UNLOCK(libc_symbol_binding) /* * IMPORTANT @@ -594,18 +688,18 @@ static int libc_accept4(int sockfd, socklen_t *addrlen, int flags) { - swrap_load_lib_function(SWRAP_LIBSOCKET, accept4); + swrap_bind_symbol_libsocket(accept4); - return swrap.fns.libc_accept4(sockfd, addr, addrlen, flags); + return swrap.libc.symbols._libc_accept4.f(sockfd, addr, addrlen, flags); } #else /* HAVE_ACCEPT4 */ static int libc_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - swrap_load_lib_function(SWRAP_LIBSOCKET, accept); + swrap_bind_symbol_libsocket(accept); - return swrap.fns.libc_accept(sockfd, addr, addrlen); + return swrap.libc.symbols._libc_accept.f(sockfd, addr, addrlen); } #endif /* HAVE_ACCEPT4 */ @@ -613,47 +707,47 @@ static int libc_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - swrap_load_lib_function(SWRAP_LIBSOCKET, bind); + swrap_bind_symbol_libsocket(bind); - return swrap.fns.libc_bind(sockfd, addr, addrlen); + return swrap.libc.symbols._libc_bind.f(sockfd, addr, addrlen); } static int libc_close(int fd) { - swrap_load_lib_function(SWRAP_LIBC, close); + swrap_bind_symbol_libc(close); - return swrap.fns.libc_close(fd); + return swrap.libc.symbols._libc_close.f(fd); } static int libc_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - swrap_load_lib_function(SWRAP_LIBSOCKET, connect); + swrap_bind_symbol_libsocket(connect); - return swrap.fns.libc_connect(sockfd, addr, addrlen); + return swrap.libc.symbols._libc_connect.f(sockfd, addr, addrlen); } static int libc_dup(int fd) { - swrap_load_lib_function(SWRAP_LIBC, dup); + swrap_bind_symbol_libc(dup); - return swrap.fns.libc_dup(fd); + return swrap.libc.symbols._libc_dup.f(fd); } static int libc_dup2(int oldfd, int newfd) { - swrap_load_lib_function(SWRAP_LIBC, dup2); + swrap_bind_symbol_libc(dup2); - return swrap.fns.libc_dup2(oldfd, newfd); + return swrap.libc.symbols._libc_dup2.f(oldfd, newfd); } #ifdef HAVE_EVENTFD static int libc_eventfd(int count, int flags) { - swrap_load_lib_function(SWRAP_LIBC, eventfd); + swrap_bind_symbol_libc(eventfd); - return swrap.fns.libc_eventfd(count, flags); + return swrap.libc.symbols._libc_eventfd.f(count, flags); } #endif @@ -664,18 +758,18 @@ static int libc_vfcntl(int fd, int cmd, va_list ap) int rc; int i; - swrap_load_lib_function(SWRAP_LIBC, fcntl); + swrap_bind_symbol_libc(fcntl); for (i = 0; i < 4; i++) { args[i] = va_arg(ap, long int); } - rc = swrap.fns.libc_fcntl(fd, - cmd, - args[0], - args[1], - args[2], - args[3]); + rc = swrap.libc.symbols._libc_fcntl.f(fd, + cmd, + args[0], -- Socket Wrapper Repository