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-265/config.h.in nss_ldap-265/config.h.in --- nss_ldap-265/config.h.in 2009-11-06 05:28:08.000000000 -0500 +++ nss_ldap-265/config.h.in 2010-01-08 17:29:49.000000000 -0500 @@ -304,6 +304,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-265/configure.in nss_ldap-265/configure.in --- nss_ldap-265/configure.in 2009-11-06 05:28:08.000000000 -0500 +++ nss_ldap-265/configure.in 2010-01-08 17:29:49.000000000 -0500 @@ -27,6 +27,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-265/depth.c nss_ldap-265/depth.c --- nss_ldap-265/depth.c 2010-01-08 17:29:49.000000000 -0500 +++ nss_ldap-265/depth.c 2010-01-08 17:29:49.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-265/depth.h nss_ldap-265/depth.h --- nss_ldap-265/depth.h 2010-01-08 17:29:49.000000000 -0500 +++ nss_ldap-265/depth.h 2010-01-08 17:29:49.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-265/ldap-hosts.c nss_ldap-265/ldap-hosts.c --- nss_ldap-265/ldap-hosts.c 2009-11-06 05:28:08.000000000 -0500 +++ nss_ldap-265/ldap-hosts.c 2010-01-08 17:33:38.000000000 -0500 @@ -66,6 +66,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> @@ -280,6 +281,11 @@ _nss_ldap_gethostbyname2_r (const char * } #endif +#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; @@ -355,6 +361,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. @@ -391,6 +402,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 @@ -403,6 +419,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 @@ -435,6 +456,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-265/ldap-nss.c nss_ldap-265/ldap-nss.c --- nss_ldap-265/ldap-nss.c 2009-11-06 05:28:08.000000000 -0500 +++ nss_ldap-265/ldap-nss.c 2010-01-08 17:29:49.000000000 -0500 @@ -93,6 +93,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 @@ -578,6 +579,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: @@ -623,6 +627,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-265/Makefile.am nss_ldap-265/Makefile.am --- nss_ldap-265/Makefile.am 2009-11-06 05:28:08.000000000 -0500 +++ nss_ldap-265/Makefile.am 2010-01-08 17:31:45.000000000 -0500 @@ -23,6 +23,7 @@ nss_ldap_so_SOURCES = ldap-nss.c ldap-pw 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 ldap-init-krb5-cache.c + dnsconfig.c irs-nss.c pagectrl.c ldap-sldap.c ldap-init-krb5-cache.c \ + depth.c nss_ldap_so_LDFLAGS = @nss_ldap_so_LDFLAGS@