Blame SOURCES/glibc-rh705465.patch

b9ba6d
2011-11-07  Andreas Schwab  <schwab@redhat.com>
b9ba6d
b9ba6d
	* nss/nss_files/files-initgroups.c (_nss_files_initgroups_dyn):
b9ba6d
	Fix size of allocated buffer.
b9ba6d
b9ba6d
2011-05-10  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
b9ba6d
	[BZ #11257]
b9ba6d
	* grp/initgroups.c (internal_getgrouplist): When we found the service
b9ba6d
	list through the initgroups entry in nsswitch.conf do not always
b9ba6d
	continue on a successful lookup.  Don't always use the
b9ba6d
	__nss_group_data-ase value if it is set.
b9ba6d
	* nss/nsswitch.conf (initgroups): Change action for successful db
b9ba6d
	lookup to continue for compatibility.
b9ba6d
b9ba6d
2011-05-06  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
b9ba6d
	* nss/nss_files/files-initgroups.c (_nss_files_initgroups_dyn): Return
b9ba6d
	NSS_STATUS_NOTFOUND if no record was found.
b9ba6d
b9ba6d
2011-04-29  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
b9ba6d
	* grp/initgroups.c (internal_getgrouplist): Prefer initgroups setting
b9ba6d
	to groups setting in database lookup.
b9ba6d
	* nss/nsswitch.conf: Add initgroups entry.
b9ba6d
b9ba6d
2011-04-21  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
b9ba6d
	* nss/nss_files/files-initgroups.c (_nss_files_initgroups_dyn): Fix
b9ba6d
	problem in reallocation in last patch.
b9ba6d
b9ba6d
2011-04-19  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
b9ba6d
	* nss/nss_files/files-initgroups.c: New file.
b9ba6d
	* nss/Makefile (libnss_files-routines): Add files-initgroups.
b9ba6d
	* nss/Versions (libnss_files) [GLIBC_PRIVATE]: Export
b9ba6d
	_nss_files_initgroups_dyn.
b9ba6d
b9ba6d
2011-01-13  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
b9ba6d
	[BZ #10484]
b9ba6d
	* nss/nss_files/files-hosts.c (HOST_DB_LOOKUP): Handle overflows of
b9ba6d
	temporary buffer used to handle multi lookups locally.
b9ba6d
	* include/alloca.h: Add libc_hidden_proto for __libc_alloca_cutoff.
b9ba6d
b9ba6d
2011-01-13  Ulrich Drepper  <drepper@gmail.com>
b9ba6d
b9ba6d
	[BZ #10484]
b9ba6d
	* Versions [libc] (GLIBC_PRIVATE): Export __libc_alloca_cutoff.
b9ba6d
	* alloca_cutoff.c: Add libc_hidden_def.
b9ba6d
b9ba6d
Index: glibc-2.12-2-gc4ccff1/grp/initgroups.c
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/grp/initgroups.c
b9ba6d
+++ glibc-2.12-2-gc4ccff1/grp/initgroups.c
b9ba6d
@@ -43,6 +43,8 @@ extern int __nss_group_lookup (service_u
b9ba6d
 extern void *__nss_lookup_function (service_user *ni, const char *fct_name);
b9ba6d
 
b9ba6d
 extern service_user *__nss_group_database attribute_hidden;
b9ba6d
+static service_user *initgroups_database;
b9ba6d
+static bool use_initgroups_entry;
b9ba6d
 
b9ba6d
 
b9ba6d
 #include "compat-initgroups.c"
b9ba6d
@@ -67,32 +69,41 @@ internal_getgrouplist (const char *user,
b9ba6d
     }
b9ba6d
 #endif
b9ba6d
 
b9ba6d
-  service_user *nip = NULL;
b9ba6d
-  initgroups_dyn_function fct;
b9ba6d
   enum nss_status status = NSS_STATUS_UNAVAIL;
b9ba6d
-  int no_more;
b9ba6d
-  /* Start is one, because we have the first group as parameter.  */
b9ba6d
-  long int start = 1;
b9ba6d
+  int no_more = 0;
b9ba6d
 
b9ba6d
   /* Never store more than the starting *SIZE number of elements.  */
b9ba6d
   assert (*size > 0);
b9ba6d
   (*groupsp)[0] = group;
b9ba6d
+  /* Start is one, because we have the first group as parameter.  */
b9ba6d
+  long int start = 1;
b9ba6d
 
b9ba6d
-  if (__nss_group_database != NULL)
b9ba6d
+  if (initgroups_database == NULL)
b9ba6d
     {
b9ba6d
-      no_more = 0;
b9ba6d
-      nip = __nss_group_database;
b9ba6d
+      no_more = __nss_database_lookup ("initgroups", NULL, "",
b9ba6d
+				       &initgroups_database);
b9ba6d
+      if (no_more == 0 && initgroups_database == NULL)
b9ba6d
+	{
b9ba6d
+	  if (__nss_group_database == NULL)
b9ba6d
+	    no_more = __nss_database_lookup ("group", NULL, "compat files",
b9ba6d
+					     &__nss_group_database);
b9ba6d
+
b9ba6d
+	  initgroups_database = __nss_group_database;
b9ba6d
+	}
b9ba6d
+      else if (initgroups_database != NULL)
b9ba6d
+	{
b9ba6d
+	  assert (no_more == 0);
b9ba6d
+	  use_initgroups_entry = true;
b9ba6d
+	}
b9ba6d
     }
b9ba6d
-  else
b9ba6d
-    no_more = __nss_database_lookup ("group", NULL,
b9ba6d
-				     "compat [NOTFOUND=return] files", &nip;;
b9ba6d
 
b9ba6d
+  service_user *nip = initgroups_database;
b9ba6d
   while (! no_more)
b9ba6d
     {
b9ba6d
       long int prev_start = start;
b9ba6d
 
b9ba6d
-      fct = __nss_lookup_function (nip, "initgroups_dyn");
b9ba6d
-
b9ba6d
+      initgroups_dyn_function fct = __nss_lookup_function (nip,
b9ba6d
+							   "initgroups_dyn");
b9ba6d
       if (fct == NULL)
b9ba6d
 	status = compat_call (nip, user, group, &start, size, groupsp,
b9ba6d
 			      limit, &errno);
b9ba6d
@@ -119,7 +130,13 @@ internal_getgrouplist (const char *user,
b9ba6d
       if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
b9ba6d
 	__libc_fatal ("illegal status in internal_getgrouplist");
b9ba6d
 
b9ba6d
-      if (status != NSS_STATUS_SUCCESS
b9ba6d
+      /* For compatibility reason we will continue to look for more
b9ba6d
+	 entries using the next service even though data has already
b9ba6d
+	 been found if the nsswitch.conf file contained only a 'groups'
b9ba6d
+	 line and no 'initgroups' line.  If the latter is available
b9ba6d
+	 we always respect the status.  This means that the default
b9ba6d
+	 for successful lookups is to return.  */
b9ba6d
+      if ((use_initgroups_entry || status != NSS_STATUS_SUCCESS)
b9ba6d
 	  && nss_next_action (nip, status) == NSS_ACTION_RETURN)
b9ba6d
 	 break;
b9ba6d
 
b9ba6d
Index: glibc-2.12-2-gc4ccff1/include/alloca.h
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/include/alloca.h
b9ba6d
+++ glibc-2.12-2-gc4ccff1/include/alloca.h
b9ba6d
@@ -14,6 +14,7 @@ extern void *__alloca (size_t __size);
b9ba6d
 
b9ba6d
 extern int __libc_use_alloca (size_t size) __attribute__ ((const));
b9ba6d
 extern int __libc_alloca_cutoff (size_t size) __attribute__ ((const));
b9ba6d
+libc_hidden_proto (__libc_alloca_cutoff)
b9ba6d
 
b9ba6d
 #define __MAX_ALLOCA_CUTOFF	65536
b9ba6d
 
b9ba6d
Index: glibc-2.12-2-gc4ccff1/nptl/Versions
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/nptl/Versions
b9ba6d
+++ glibc-2.12-2-gc4ccff1/nptl/Versions
b9ba6d
@@ -27,6 +27,7 @@ libc {
b9ba6d
     pthread_cond_broadcast; pthread_cond_timedwait;
b9ba6d
   }
b9ba6d
   GLIBC_PRIVATE {
b9ba6d
+    __libc_alloca_cutoff;
b9ba6d
     # Internal libc interface to libpthread
b9ba6d
     __libc_dl_error_tsd;
b9ba6d
   }
b9ba6d
Index: glibc-2.12-2-gc4ccff1/nptl/alloca_cutoff.c
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/nptl/alloca_cutoff.c
b9ba6d
+++ glibc-2.12-2-gc4ccff1/nptl/alloca_cutoff.c
b9ba6d
@@ -34,3 +34,4 @@ __libc_alloca_cutoff (size_t size)
b9ba6d
 			  assume the maximum available stack space.  */
b9ba6d
 		       ?: __MAX_ALLOCA_CUTOFF * 4));
b9ba6d
 }
b9ba6d
+libc_hidden_def (__libc_alloca_cutoff)
b9ba6d
Index: glibc-2.12-2-gc4ccff1/nss/Makefile
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/nss/Makefile
b9ba6d
+++ glibc-2.12-2-gc4ccff1/nss/Makefile
b9ba6d
@@ -63,7 +63,7 @@ vpath %.c $(subdir-dirs)
b9ba6d
 
b9ba6d
 
b9ba6d
 libnss_files-routines	:= $(addprefix files-,$(databases)) \
b9ba6d
-			   files-have_o_cloexec
b9ba6d
+			   files-initgroups files-have_o_cloexec
b9ba6d
 distribute		+= files-XXX.c files-parse.c
b9ba6d
 
b9ba6d
 
b9ba6d
Index: glibc-2.12-2-gc4ccff1/nss/Versions
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/nss/Versions
b9ba6d
+++ glibc-2.12-2-gc4ccff1/nss/Versions
b9ba6d
@@ -95,5 +95,7 @@ libnss_files {
b9ba6d
     _nss_netgroup_parseline;
b9ba6d
     _nss_files_getpublickey;
b9ba6d
     _nss_files_getsecretkey;
b9ba6d
+
b9ba6d
+    _nss_files_initgroups_dyn;
b9ba6d
   }
b9ba6d
 }
b9ba6d
Index: glibc-2.12-2-gc4ccff1/nss/nss_files/files-hosts.c
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/nss/nss_files/files-hosts.c
b9ba6d
+++ glibc-2.12-2-gc4ccff1/nss/nss_files/files-hosts.c
b9ba6d
@@ -129,19 +129,22 @@ _nss_files_get##name##_r (proto,					   
b9ba6d
 	  && _res_hconf.flags & HCONF_FLAG_MULTI)			      \
b9ba6d
 	{								      \
b9ba6d
 	  /* We have to get all host entries from the file.  */		      \
b9ba6d
-	  const size_t tmp_buflen = MIN (buflen, 4096);			      \
b9ba6d
-	  char tmp_buffer[tmp_buflen]					      \
b9ba6d
+	  size_t tmp_buflen = MIN (buflen, 4096);			      \
b9ba6d
+	  char tmp_buffer_stack[tmp_buflen]				      \
b9ba6d
 	    __attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));\
b9ba6d
+	  char *tmp_buffer = tmp_buffer_stack;				      \
b9ba6d
 	  struct hostent tmp_result_buf;				      \
b9ba6d
 	  int naddrs = 1;						      \
b9ba6d
 	  int naliases = 0;						      \
b9ba6d
 	  char *bufferend;						      \
b9ba6d
+	  bool tmp_buffer_malloced = false;				      \
b9ba6d
 									      \
b9ba6d
 	  while (result->h_aliases[naliases] != NULL)			      \
b9ba6d
 	    ++naliases;							      \
b9ba6d
 									      \
b9ba6d
 	  bufferend = (char *) &result->h_aliases[naliases + 1];	      \
b9ba6d
 									      \
b9ba6d
+	again:								      \
b9ba6d
 	  while ((status = internal_getent (&tmp_result_buf, tmp_buffer,      \
b9ba6d
 					    tmp_buflen, errnop H_ERRNO_ARG    \
b9ba6d
 					    EXTRA_ARGS_VALUE))		      \
b9ba6d
@@ -182,7 +185,7 @@ _nss_files_get##name##_r (proto,					   
b9ba6d
 		    }							      \
b9ba6d
 		  /* If the real name is different add it also to the	      \
b9ba6d
 		     aliases.  This means that there is a duplication	      \
b9ba6d
-		     in the alias list but this is really the users	      \
b9ba6d
+		     in the alias list but this is really the user's	      \
b9ba6d
 		     problem.  */					      \
b9ba6d
 		  if (strcmp (old_result->h_name,			      \
b9ba6d
 			      tmp_result_buf.h_name) != 0)		      \
b9ba6d
@@ -204,7 +207,7 @@ _nss_files_get##name##_r (proto,					   
b9ba6d
 		      *errnop = ERANGE;					      \
b9ba6d
 		      *herrnop = NETDB_INTERNAL;			      \
b9ba6d
 		      status = NSS_STATUS_TRYAGAIN;			      \
b9ba6d
-		      break;						      \
b9ba6d
+		      goto out;						      \
b9ba6d
 		    }							      \
b9ba6d
 									      \
b9ba6d
 		  new_h_addr_list =					      \
b9ba6d
@@ -268,8 +271,54 @@ _nss_files_get##name##_r (proto,					   
b9ba6d
 		}							      \
b9ba6d
 	    }								      \
b9ba6d
 									      \
b9ba6d
-	  if (status != NSS_STATUS_TRYAGAIN)				      \
b9ba6d
+	  if (status == NSS_STATUS_TRYAGAIN)				      \
b9ba6d
+	    {								      \
b9ba6d
+	      size_t newsize = 2 * tmp_buflen;				      \
b9ba6d
+	      if (tmp_buffer_malloced)					      \
b9ba6d
+		{							      \
b9ba6d
+		  char *newp = realloc (tmp_buffer, newsize);		      \
b9ba6d
+		  if (newp != NULL)					      \
b9ba6d
+		    {							      \
b9ba6d
+		      assert ((((uintptr_t) newp)			      \
b9ba6d
+			       & (__alignof__ (struct hostent_data) - 1))     \
b9ba6d
+			      == 0);					      \
b9ba6d
+		      tmp_buffer = newp;				      \
b9ba6d
+		      tmp_buflen = newsize;				      \
b9ba6d
+		      goto again;					      \
b9ba6d
+		    }							      \
b9ba6d
+		}							      \
b9ba6d
+	      else if (!__libc_use_alloca (buflen + newsize))		      \
b9ba6d
+		{							      \
b9ba6d
+		  tmp_buffer = malloc (newsize);			      \
b9ba6d
+		  if (tmp_buffer != NULL)				      \
b9ba6d
+		    {							      \
b9ba6d
+		      assert ((((uintptr_t) tmp_buffer)			      \
b9ba6d
+			       & (__alignof__ (struct hostent_data) - 1))     \
b9ba6d
+			      == 0);					      \
b9ba6d
+		      tmp_buffer_malloced = true;			      \
b9ba6d
+		      tmp_buflen = newsize;				      \
b9ba6d
+		      goto again;					      \
b9ba6d
+		    }							      \
b9ba6d
+		}							      \
b9ba6d
+	      else							      \
b9ba6d
+		{							      \
b9ba6d
+		  tmp_buffer						      \
b9ba6d
+		    = extend_alloca (tmp_buffer, tmp_buflen,		      \
b9ba6d
+				     newsize				      \
b9ba6d
+				     + __alignof__ (struct hostent_data));    \
b9ba6d
+		  tmp_buffer = (char *) (((uintptr_t) tmp_buffer	      \
b9ba6d
+					  + __alignof__ (struct hostent_data) \
b9ba6d
+					  - 1)				      \
b9ba6d
+					 & ~(__alignof__ (struct hostent_data)\
b9ba6d
+					     - 1));			      \
b9ba6d
+		  goto again;						      \
b9ba6d
+		}							      \
b9ba6d
+	    }								      \
b9ba6d
+	  else								      \
b9ba6d
 	    status = NSS_STATUS_SUCCESS;				      \
b9ba6d
+	out:								      \
b9ba6d
+	  if (tmp_buffer_malloced)					      \
b9ba6d
+	    free (tmp_buffer);						      \
b9ba6d
 	}								      \
b9ba6d
 									      \
b9ba6d
 									      \
b9ba6d
Index: glibc-2.12-2-gc4ccff1/nss/nss_files/files-initgroups.c
b9ba6d
===================================================================
b9ba6d
--- /dev/null
b9ba6d
+++ glibc-2.12-2-gc4ccff1/nss/nss_files/files-initgroups.c
b9ba6d
@@ -0,0 +1,137 @@
b9ba6d
+/* Initgroups handling in nss_files module.
b9ba6d
+   Copyright (C) 2011 Free Software Foundation, Inc.
b9ba6d
+   This file is part of the GNU C Library.
b9ba6d
+
b9ba6d
+   The GNU C Library is free software; you can redistribute it and/or
b9ba6d
+   modify it under the terms of the GNU Lesser General Public
b9ba6d
+   License as published by the Free Software Foundation; either
b9ba6d
+   version 2.1 of the License, or (at your option) any later version.
b9ba6d
+
b9ba6d
+   The GNU C Library is distributed in the hope that it will be useful,
b9ba6d
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
b9ba6d
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b9ba6d
+   Lesser General Public License for more details.
b9ba6d
+
b9ba6d
+   You should have received a copy of the GNU Lesser General Public
b9ba6d
+   License along with the GNU C Library; if not, write to the Free
b9ba6d
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
b9ba6d
+   02111-1307 USA.  */
b9ba6d
+
b9ba6d
+#include <alloca.h>
b9ba6d
+#include <errno.h>
b9ba6d
+#include <grp.h>
b9ba6d
+#include <nss.h>
b9ba6d
+#include <stdio_ext.h>
b9ba6d
+#include <string.h>
b9ba6d
+#include <sys/param.h>
b9ba6d
+
b9ba6d
+enum nss_status
b9ba6d
+_nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
b9ba6d
+			   long int *size, gid_t **groupsp, long int limit,
b9ba6d
+			   int *errnop)
b9ba6d
+{
b9ba6d
+  FILE *stream = fopen ("/etc/group", "re");
b9ba6d
+  if (stream == NULL)
b9ba6d
+    {
b9ba6d
+      *errnop = errno;
b9ba6d
+      return *errnop == ENOMEM ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
b9ba6d
+    }
b9ba6d
+
b9ba6d
+  /* No other thread using this stream.  */
b9ba6d
+  __fsetlocking (stream, FSETLOCKING_BYCALLER);
b9ba6d
+
b9ba6d
+  char *line = NULL;
b9ba6d
+  size_t linelen = 0;
b9ba6d
+  enum nss_status status = NSS_STATUS_SUCCESS;
b9ba6d
+  bool any = false;
b9ba6d
+
b9ba6d
+  size_t buflen = 1024;
b9ba6d
+  void *buffer = alloca (buflen);
b9ba6d
+  bool buffer_use_malloc = false;
b9ba6d
+
b9ba6d
+  gid_t *groups = *groupsp;
b9ba6d
+
b9ba6d
+  /* We have to iterate over the entire file.  */
b9ba6d
+  while (!feof_unlocked (stream))
b9ba6d
+    {
b9ba6d
+      ssize_t n = getline (&line, &linelen, stream);
b9ba6d
+      if (n < 0)
b9ba6d
+	{
b9ba6d
+	  if (! feof_unlocked (stream))
b9ba6d
+	    status = ((*errnop = errno) == ENOMEM
b9ba6d
+		      ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL);
b9ba6d
+	  break;
b9ba6d
+	}
b9ba6d
+
b9ba6d
+      struct group grp;
b9ba6d
+      int res;
b9ba6d
+      while ((res = _nss_files_parse_grent (line, &grp, buffer, buflen,
b9ba6d
+					    errnop)) == -1)
b9ba6d
+	{
b9ba6d
+	  size_t newbuflen = 2 * buflen;
b9ba6d
+	  if (buffer_use_malloc || ! __libc_use_alloca (buflen + newbuflen))
b9ba6d
+	    {
b9ba6d
+	      void *newbuf = realloc (buffer_use_malloc ? buffer : NULL,
b9ba6d
+				      newbuflen);
b9ba6d
+	      if (newbuf == NULL)
b9ba6d
+		{
b9ba6d
+		  *errnop = ENOMEM;
b9ba6d
+		  status = NSS_STATUS_TRYAGAIN;
b9ba6d
+		  goto out;
b9ba6d
+		}
b9ba6d
+	      buffer = newbuf;
b9ba6d
+	      buflen = newbuflen;
b9ba6d
+	      buffer_use_malloc = true;
b9ba6d
+	    }
b9ba6d
+	  else
b9ba6d
+	    buffer = extend_alloca (buffer, buflen, newbuflen);
b9ba6d
+	}
b9ba6d
+
b9ba6d
+      if (res > 0 && grp.gr_gid != group)
b9ba6d
+	for (char **m = grp.gr_mem; *m != NULL; ++m)
b9ba6d
+	  if (strcmp (*m, user) == 0)
b9ba6d
+	    {
b9ba6d
+	      /* Matches user.  Insert this group.  */
b9ba6d
+	      if (*start == *size)
b9ba6d
+		{
b9ba6d
+		  /* Need a bigger buffer.  */
b9ba6d
+		  if (limit > 0 && *size == limit)
b9ba6d
+		    /* We reached the maximum.  */
b9ba6d
+		    goto out;
b9ba6d
+
b9ba6d
+		  long int newsize;
b9ba6d
+		  if (limit <= 0)
b9ba6d
+		    newsize = 2 * *size;
b9ba6d
+		  else
b9ba6d
+		    newsize = MIN (limit, 2 * *size);
b9ba6d
+
b9ba6d
+		  gid_t *newgroups = realloc (groups,
b9ba6d
+					      newsize * sizeof (*groups));
b9ba6d
+		  if (newgroups == NULL)
b9ba6d
+		    {
b9ba6d
+		      *errnop = ENOMEM;
b9ba6d
+		      status = NSS_STATUS_TRYAGAIN;
b9ba6d
+		      goto out;
b9ba6d
+		    }
b9ba6d
+		  *groupsp = groups = newgroups;
b9ba6d
+		  *size = newsize;
b9ba6d
+		}
b9ba6d
+
b9ba6d
+	      groups[*start] = grp.gr_gid;
b9ba6d
+	      *start += 1;
b9ba6d
+	      any = true;
b9ba6d
+
b9ba6d
+	      break;
b9ba6d
+	    }
b9ba6d
+    }
b9ba6d
+
b9ba6d
+ out:
b9ba6d
+  /* Free memory.  */
b9ba6d
+  if (buffer_use_malloc)
b9ba6d
+    free (buffer);
b9ba6d
+  free (line);
b9ba6d
+
b9ba6d
+  fclose (stream);
b9ba6d
+
b9ba6d
+  return status == NSS_STATUS_SUCCESS && !any ? NSS_STATUS_NOTFOUND : status;
b9ba6d
+}
b9ba6d
Index: glibc-2.12-2-gc4ccff1/nss/nsswitch.conf
b9ba6d
===================================================================
b9ba6d
--- glibc-2.12-2-gc4ccff1.orig/nss/nsswitch.conf
b9ba6d
+++ glibc-2.12-2-gc4ccff1/nss/nsswitch.conf
b9ba6d
@@ -5,6 +5,7 @@
b9ba6d
 
b9ba6d
 passwd:		db files
b9ba6d
 group:		db files
b9ba6d
+initgroups:	db [SUCCESS=continue] files
b9ba6d
 shadow:		db files
b9ba6d
 gshadow:	files
b9ba6d