svn commit: r275020 - head/lib/libc/net

Dag-Erling Smørgrav des at FreeBSD.org
Tue Nov 25 09:47:16 UTC 2014


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 + at 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);


More information about the svn-src-all mailing list