Author: des
Date: Tue Nov 25 09:47:15 2014
New Revision: 275020
URL: https://svnweb.freebsd.org/changeset/base/275020

Log:
  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

Modified:
  head/lib/libc/net/nsdispatch.c

Modified: head/lib/libc/net/nsdispatch.c
==============================================================================
--- head/lib/libc/net/nsdispatch.c      Tue Nov 25 08:39:46 2014        
(r275019)
+++ head/lib/libc/net/nsdispatch.c      Tue Nov 25 09:47:15 2014        
(r275020)
@@ -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);
@@ -613,6 +616,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;
@@ -644,7 +648,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,
@@ -713,12 +718,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",
@@ -750,6 +756,7 @@ _nsdispatch(void *retval, const ns_dtab 
 
        if (isthreaded)
                (void)_pthread_rwlock_unlock(&nss_lock);
+       --st->dispatch_depth;
 fin:
        errno = serrno;
        return (result);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to