Author: des
Date: Thu Jul  9 13:30:37 2015
New Revision: 285317
URL: https://svnweb.freebsd.org/changeset/base/285317

Log:
  MFH (r275020): partial fix for getgrouplist() in group_compat case
  
  PR:           190055
  Approved by:  re (marius)

Modified:
  stable/10/lib/libc/net/nsdispatch.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/net/nsdispatch.c
==============================================================================
--- stable/10/lib/libc/net/nsdispatch.c Thu Jul  9 13:23:29 2015        
(r285316)
+++ stable/10/lib/libc/net/nsdispatch.c Thu Jul  9 13:30:37 2015        
(r285317)
@@ -132,14 +132,17 @@ static    void                    
*nss_cache_cycle_preventio
 #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 
        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 
                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 
                                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 
 
        if (isthreaded)
                (void)_pthread_rwlock_unlock(&nss_lock);
+       --st->dispatch_depth;
 fin:
        errno = serrno;
        return (result);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to