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
This commit is contained in:
parent
4ab8910605
commit
83804ea074
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user