diff options
author | zml <zml@FreeBSD.org> | 2009-05-27 17:01:59 +0000 |
---|---|---|
committer | zml <zml@FreeBSD.org> | 2009-05-27 17:01:59 +0000 |
commit | b186e91180da0abaa602da3390c0d96d447be697 (patch) | |
tree | 6403b1bf47bfbee168f1e1cc5d5d827f9e381c29 /lib | |
parent | f9be7478fe74c8b453240e0182928d5dce69b5b9 (diff) | |
download | FreeBSD-src-b186e91180da0abaa602da3390c0d96d447be697.zip FreeBSD-src-b186e91180da0abaa602da3390c0d96d447be697.tar.gz |
Fix an issue when nss fallback routines are used in a multithreaded application.
Reviewed by: bushman
Approved by: dfr (mentor)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/include/nss_tls.h | 1 | ||||
-rw-r--r-- | 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 13ab367..6253ec6 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 9495443..162d592 100644 --- a/lib/libc/net/nsdispatch.c +++ b/lib/libc/net/nsdispatch.c @@ -80,12 +80,14 @@ __FBSDID("$FreeBSD$"); #define _NS_PRIVATE #include <nsswitch.h> #include <pthread.h> +#include <pthread_np.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h> #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", |