From 6d722173685572838133ef24c7513faac39fc3e9 Mon Sep 17 00:00:00 2001 From: Zachary Loafman Date: Wed, 27 May 2009 17:01:59 +0000 Subject: [PATCH] Fix an issue when nss fallback routines are used in a multithreaded application. Reviewed by: bushman Approved by: dfr (mentor) --- lib/libc/include/nss_tls.h | 1 + lib/libc/net/nsdispatch.c | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/libc/include/nss_tls.h b/lib/libc/include/nss_tls.h index 13ab367d06b5..6253ec6f5dd0 100644 --- a/lib/libc/include/nss_tls.h +++ b/lib/libc/include/nss_tls.h @@ -67,6 +67,7 @@ name##_getstate(struct name##_state **p) \ *p = calloc(1, sizeof(**p)); \ if (*p == NULL) \ return (ENOMEM); \ + memset(*p, 0, sizeof(**p)); \ rv = _pthread_setspecific(name##_state_key, *p); \ if (rv != 0) { \ free(*p); \ diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c index 9495443ce7f8..162d592acf68 100644 --- a/lib/libc/net/nsdispatch.c +++ b/lib/libc/net/nsdispatch.c @@ -80,12 +80,14 @@ __FBSDID("$FreeBSD$"); #define _NS_PRIVATE #include #include +#include #include #include #include #include #include #include "un-namespace.h" +#include "nss_tls.h" #include "libc_private.h" #ifdef NS_CACHING #include "nscache.h" @@ -143,7 +145,11 @@ static void *nss_cache_cycle_prevention_func = NULL; * which in turn calls nsdispatch, which should call fallback * function) are not supported */ -static int fallback_dispatch = 0; +struct fb_state { + int fb_dispatch; +}; +static void fb_endstate(void *); +NSS_TLS_HANDLING(fb); /* * Attempt to spew relatively uniform messages to syslog. @@ -598,6 +604,11 @@ nss_method_lookup(const char *source, const char *database, return (NULL); } +static void +fb_endstate(void *p) +{ + free(p); +} __weak_reference(_nsdispatch, nsdispatch); @@ -611,6 +622,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, nss_method method, fb_method; void *mdata; int isthreaded, serrno, i, result, srclistsize; + struct fb_state *st; #ifdef NS_CACHING nss_cache_data cache_data; @@ -630,12 +642,19 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, goto fin; } } + + result = fb_getstate(&st); + if (result != 0) { + result = NS_UNAVAIL; + goto fin; + } + result = nss_configure(); if (result != 0) { result = NS_UNAVAIL; goto fin; } - if (fallback_dispatch == 0) { + if (st->fb_dispatch == 0) { dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap), string_compare); fb_method = nss_method_lookup(NSSRC_FALLBACK, database, @@ -702,12 +721,12 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, break; } else { if (fb_method != NULL) { - fallback_dispatch = 1; + st->fb_dispatch = 1; va_start(ap, defaults); result = fb_method(retval, (void *)srclist[i].name, ap); va_end(ap); - fallback_dispatch = 0; + st->fb_dispatch = 0; } else nss_log(LOG_DEBUG, "%s, %s, %s, not found, " "and no fallback provided",