Check if we can use thread-local storage, and if we can, use one to avoid a self-deadlock if we recurse into our own host resolution routines from inside of another lookup attempt. diff -up nss_ldap-253/config.h.in nss_ldap-253/config.h.in --- nss_ldap-253/config.h.in 2009-12-11 16:54:38.000000000 -0500 +++ nss_ldap-253/config.h.in 2009-12-11 16:56:11.000000000 -0500 @@ -295,6 +295,11 @@ /* Define to 1 if you have the <thread.h> header file. */ #undef HAVE_THREAD_H +/* Define if your toolchain supports thread-local storage, which can be used + for detecting self- and mutual-recursion problems when performing + host/address lookups. */ +#undef HAVE_THREAD_LOCAL_STORAGE + /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H diff -up nss_ldap-253/configure.in nss_ldap-253/configure.in --- nss_ldap-253/configure.in 2009-12-11 16:53:18.000000000 -0500 +++ nss_ldap-253/configure.in 2009-12-11 16:54:19.000000000 -0500 @@ -26,6 +26,14 @@ dnl AC_ARG_ENABLE(debugging, [ --enable-debugging enable debug code ], [AC_DEFINE(DEBUG)]) +AC_MSG_CHECKING(for thread-local storage) +AC_TRY_COMPILE([],[static __thread int _nss_ldap_recursion_count;], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_THREAD_LOCAL_STORAGE,1,[Define if your toolchain supports thread-local storage, which can be used for detecting self- and mutual-recursion problems when performing host/address lookups.]) + ], + AC_MSG_RESULT(no)) + dnl dnl --enable-paged-results is now deprecated; if this option is set, dnl then paged results will be enabled by default. However, it can diff -up nss_ldap-253/depth.c nss_ldap-253/depth.c --- nss_ldap-253/depth.c 2009-12-11 16:48:32.000000000 -0500 +++ nss_ldap-253/depth.c 2009-12-11 16:57:05.000000000 -0500 @@ -0,0 +1,24 @@ +#include "config.h" +#include "depth.h" + +#ifdef HAVE_THREAD_LOCAL_STORAGE +static __thread int depth = 0; + +int +_nss_ldap_get_depth (void) +{ + return depth; +} + +int +_nss_ldap_inc_depth (void) +{ + return ++depth; +} + +int +_nss_ldap_dec_depth (void) +{ + return --depth; +} +#endif diff -up nss_ldap-253/depth.h nss_ldap-253/depth.h --- nss_ldap-253/depth.h 2009-12-11 16:48:28.000000000 -0500 +++ nss_ldap-253/depth.h 2009-12-11 16:48:23.000000000 -0500 @@ -0,0 +1,3 @@ +int _nss_ldap_get_depth (void); +int _nss_ldap_inc_depth (void); +int _nss_ldap_dec_depth (void); diff -up nss_ldap-253/ldap-hosts.c nss_ldap-253/ldap-hosts.c --- nss_ldap-253/ldap-hosts.c 2009-12-11 16:49:58.000000000 -0500 +++ nss_ldap-253/ldap-hosts.c 2009-12-11 16:57:56.000000000 -0500 @@ -63,6 +63,7 @@ static char rcsId[] = #include "ldap-nss.h" #include "ldap-hosts.h" #include "util.h" +#include "depth.h" #ifdef HAVE_PORT_AFTER_H #include <port_after.h> @@ -270,6 +271,11 @@ _nss_ldap_gethostbyname2_r (const char * NSS_STATUS status; ldap_args_t a; +#ifdef HAVE_THREAD_LOCAL_STORAGE + if (_nss_ldap_get_depth() > 0) + return NSS_STATUS_UNAVAIL; +#endif + LA_INIT (a); LA_STRING (a) = name; LA_TYPE (a) = LA_TYPE_STRING; @@ -345,6 +351,11 @@ _nss_ldap_gethostbyaddr_r (struct in_add NSS_STATUS status; ldap_args_t a; +#ifdef HAVE_THREAD_LOCAL_STORAGE + if (_nss_ldap_get_depth() > 0) + return NSS_STATUS_UNAVAIL; +#endif + /* if querying by IPv6 address, make sure the address is "normalized" -- * it should contain no leading zeros and all components of the address. * still we can't fit an IPv6 address in an int, so who cares for now. @@ -381,6 +392,11 @@ _nss_ldap_sethostent_r (nss_backend_t * #endif #if defined(HAVE_NSS_H) || defined(HAVE_NSSWITCH_H) { +#ifdef HAVE_THREAD_LOCAL_STORAGE + if (_nss_ldap_get_depth() > 0) + return NSS_STATUS_UNAVAIL; +#endif + LOOKUP_SETENT (hosts_context); } #endif @@ -393,6 +409,11 @@ _nss_ldap_endhostent_r (nss_backend_t * #endif #if defined(HAVE_NSS_H) || defined(HAVE_NSSWITCH_H) { +#ifdef HAVE_THREAD_LOCAL_STORAGE + if (_nss_ldap_get_depth() > 0) + return NSS_STATUS_UNAVAIL; +#endif + LOOKUP_ENDENT (hosts_context); } #endif @@ -425,6 +446,11 @@ _nss_ldap_gethostent_r (struct hostent * { NSS_STATUS status; +#ifdef HAVE_THREAD_LOCAL_STORAGE + if (_nss_ldap_get_depth() > 0) + return NSS_STATUS_UNAVAIL; +#endif + status = _nss_ldap_getent (&hosts_context, result, buffer, diff -up nss_ldap-253/ldap-nss.c nss_ldap-253/ldap-nss.c --- nss_ldap-253/ldap-nss.c 2009-12-11 16:48:54.000000000 -0500 +++ nss_ldap-253/ldap-nss.c 2009-12-11 16:57:24.000000000 -0500 @@ -90,6 +90,7 @@ static char rcsId[] = #include "util.h" #include "dnsconfig.h" #include "pagectrl.h" +#include "depth.h" #if defined(HAVE_THREAD_H) && !defined(_AIX) #ifdef HAVE_PTHREAD_ATFORK @@ -582,6 +583,9 @@ _nss_ldap_enter (void) debug ("==> _nss_ldap_enter"); NSS_LDAP_LOCK (__lock); +#ifdef HAVE_THREAD_LOCAL_STORAGE + _nss_ldap_inc_depth(); +#endif /* * Patch for Debian Bug 130006: @@ -627,6 +631,9 @@ _nss_ldap_leave (void) } #endif /* HAVE_SIGACTION */ +#ifdef HAVE_THREAD_LOCAL_STORAGE + _nss_ldap_dec_depth(); +#endif NSS_LDAP_UNLOCK (__lock); debug ("<== _nss_ldap_leave"); diff -up nss_ldap-253/Makefile.am nss_ldap-253/Makefile.am --- nss_ldap-253/Makefile.am 2009-12-11 16:49:29.000000000 -0500 +++ nss_ldap-253/Makefile.am 2009-12-11 16:49:34.000000000 -0500 @@ -22,7 +22,7 @@ nss_ldap_so_SOURCES = ldap-nss.c ldap-pw ldap-hosts.c ldap-network.c ldap-proto.c ldap-spwd.c \ ldap-alias.c ldap-service.c ldap-schema.c ldap-ethers.c \ ldap-bp.c ldap-automount.c util.c ltf.c snprintf.c resolve.c \ - dnsconfig.c irs-nss.c pagectrl.c ldap-sldap.c + dnsconfig.c irs-nss.c pagectrl.c ldap-sldap.c depth.c nss_ldap_so_LDFLAGS = @nss_ldap_so_LDFLAGS@