diff options
author | des <des@FreeBSD.org> | 2015-07-09 13:30:37 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2015-07-09 13:30:37 +0000 |
commit | e9222c7afa737129005e2eb7069a9136b82170e8 (patch) | |
tree | 5526f458a79481d940e334e70f6d40729d317850 /lib/libc/net | |
parent | 8415194b187c9fc6ac0e6e1fdae51a91e7f7ccb5 (diff) | |
download | FreeBSD-src-e9222c7afa737129005e2eb7069a9136b82170e8.zip FreeBSD-src-e9222c7afa737129005e2eb7069a9136b82170e8.tar.gz |
MFH (r275020): partial fix for getgrouplist() in group_compat case
PR: 190055
Approved by: re (marius)
Diffstat (limited to 'lib/libc/net')
-rw-r--r-- | lib/libc/net/nsdispatch.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c index 4fbc9ba..b261f74 100644 --- a/lib/libc/net/nsdispatch.c +++ b/lib/libc/net/nsdispatch.c @@ -132,14 +132,17 @@ static void *nss_cache_cycle_prevention_func = NULL; #endif /* - * When this is set to 1, nsdispatch won't use nsswitch.conf - * but will consult the 'defaults' source list only. - * NOTE: nested fallbacks (when nsdispatch calls fallback functions, - * which in turn calls nsdispatch, which should call fallback - * function) are not supported + * We keep track of nsdispatch() nesting depth in dispatch_depth. When a + * fallback method is invoked from nsdispatch(), we temporarily set + * fallback_depth to the current dispatch depth plus one. Subsequent + * calls at that exact depth will run in fallback mode (restricted to the + * same source as the call that was handled by the fallback method), while + * calls below that depth will be handled normally, allowing fallback + * methods to perform arbitrary lookups. */ struct fb_state { - int fb_dispatch; + int dispatch_depth; + int fallback_depth; }; static void fb_endstate(void *); NSS_TLS_HANDLING(fb); @@ -616,6 +619,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, void *mdata; int isthreaded, serrno, i, result, srclistsize; struct fb_state *st; + int saved_depth; #ifdef NS_CACHING nss_cache_data cache_data; @@ -647,7 +651,8 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, result = NS_UNAVAIL; goto fin; } - if (st->fb_dispatch == 0) { + ++st->dispatch_depth; + if (st->dispatch_depth > st->fallback_depth) { dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap), string_compare); fb_method = nss_method_lookup(NSSRC_FALLBACK, database, @@ -716,12 +721,13 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, break; } else { if (fb_method != NULL) { - st->fb_dispatch = 1; + saved_depth = st->fallback_depth; + st->fallback_depth = st->dispatch_depth + 1; va_start(ap, defaults); result = fb_method(retval, (void *)srclist[i].name, ap); va_end(ap); - st->fb_dispatch = 0; + st->fallback_depth = saved_depth; } else nss_log(LOG_DEBUG, "%s, %s, %s, not found, " "and no fallback provided", @@ -753,6 +759,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, if (isthreaded) (void)_pthread_rwlock_unlock(&nss_lock); + --st->dispatch_depth; fin: errno = serrno; return (result); |