summaryrefslogtreecommitdiffstats
path: root/lib/libc/net
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2014-11-25 09:47:15 +0000
committerdes <des@FreeBSD.org>2014-11-25 09:47:15 +0000
commit44c4e24d2a4d97b8eceb52ca454447cc19cfd42e (patch)
tree7af0b1c9ed178688ccdea34280f37bf58134427e /lib/libc/net
parent83f6d12d654df1171caee01d8a80c17aa3f46ebd (diff)
downloadFreeBSD-src-44c4e24d2a4d97b8eceb52ca454447cc19cfd42e.zip
FreeBSD-src-44c4e24d2a4d97b8eceb52ca454447cc19cfd42e.tar.gz
The fallback flag in nsdispatch prevents the fallback implementation of
getgroupmembership() from invoking the correct backend in the compat case. Replace it with a nesting depth counter so it only blocks one level (the first is the group -> group_compat translation, the second is the actual backend). This is one of two bugs that break getgrouplist() in the compat case, the second being that the backend's own getgroupmembership() method is ignored. Unfortunately, that is not easily fixable without a redesign of our nss implementation (which is also needed to implement the +@group syntax in /etc/passwd). PR: 190055 MFC after: 1 week
Diffstat (limited to 'lib/libc/net')
-rw-r--r--lib/libc/net/nsdispatch.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c
index c23315c..4de1df3 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);
@@ -613,6 +616,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;
@@ -644,7 +648,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,
@@ -713,12 +718,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",
@@ -750,6 +756,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);
OpenPOWER on IntegriCloud