[nss_db] - import patch to handle initgroups directly rather than forcing libc to use the enumeration interfa

Nalin Dahyabhai nalin at fedoraproject.org
Wed May 18 18:06:40 UTC 2011


commit 65a7a67a7c0bc53d9cee78dd4f7c501b5387b76c
Author: Nalin Dahyabhai <nalin at redhat.com>
Date:   Wed May 18 14:06:00 2011 -0400

    - import patch to handle initgroups directly rather than forcing libc to use the enumeration interfaces, which could result in two threads calling initgroups() at the same time to both get a subset of the right answers (#705466)

 d-nss_db-initgr.patch |  254 +++++++++++++++++++++++++++++++++++++++++++++++++
 nss_db.spec           |   10 ++-
 2 files changed, 263 insertions(+), 1 deletions(-)
---
diff --git a/d-nss_db-initgr.patch b/d-nss_db-initgr.patch
new file mode 100644
index 0000000..d70c9c7
--- /dev/null
+++ b/d-nss_db-initgr.patch
@@ -0,0 +1,254 @@
+diff -up ./src/db-initgroups.c.initgr ./src/db-initgroups.c
+--- a/src/db-initgroups.c.initgr	2011-04-21 13:37:34.913687000 -0400
++++ b/src/db-initgroups.c	2011-04-21 14:13:11.826667000 -0400
+@@ -0,0 +1,192 @@
++/* Initgroups handling in nss_db module.
++   Copyright (C) 2011 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Library General Public License as
++   published by the Free Software Foundation; either version 2 of the
++   License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Library General Public License for more details.
++
++   You should have received a copy of the GNU Library General Public
++   License along with the GNU C Library; see the file COPYING.LIB.  If not,
++   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <alloca.h>
++#include <ctype.h>
++#include <errno.h>
++#include <grp.h>
++#include <paths.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/param.h>
++
++#include "nss_db.h"
++
++/* Declared in glibc's include/grp.h.  */
++extern int _nss_files_parse_grent (char *line, struct group *result,
++                                   void *data, size_t datalen, int *errnop);
++
++
++enum nss_status
++_nss_db_initgroups_dyn (const char *user, gid_t group, long int *start,
++			long int *size, gid_t **groupsp, long int limit,
++			int *errnop)
++{
++  DB *db = NULL;
++  DB_ENV *dbenv = NULL;
++
++  /* Open the database.  */
++  enum nss_status status = internal_setent (_PATH_VARDB "group.db", &db,
++					    &dbenv);
++  if (status == NSS_STATUS_SUCCESS)
++    {
++      unsigned int entidx = 0;
++
++      size_t linelen = 1024;
++      void *line = alloca (linelen);
++      bool line_use_malloc = false;
++
++      size_t buflen = 1024;
++      void *buffer = alloca (buflen);
++      bool buffer_use_malloc = false;
++
++      size_t alloca_used = linelen + buflen;
++
++      gid_t *groups = *groupsp;
++
++      while (1)
++	{
++	  char buf[20];
++	  DBT key;
++
++	  key.size = snprintf (key.data = buf, sizeof buf, "0%u", entidx++);
++	  key.flags = 0;
++
++	  DBT value;
++	  value.flags = 0;
++	  int err = db->get (db, NULL, &key, &value, 0);
++	  if (err)
++	    {
++	      if (err != DB_NOTFOUND)
++		{
++		  if (err > 0)
++		    *errnop = err;
++		  status = NSS_STATUS_UNAVAIL;
++		}
++	      break;
++	    }
++
++	  /* We need a copy of the value we can modify.  */
++	  if (linelen < value.size)
++	    {
++	      size_t newlinelen = MAX (2 * linelen, value.size);
++
++	      if (line_use_malloc 
++		  || ! __libc_use_alloca (alloca_used + newlinelen))
++		{
++		  void *newline = realloc (line_use_malloc ? line : NULL,
++					   newlinelen);
++		  if (newline == NULL)
++		    {
++		      *errnop = ENOMEM;
++		      status = NSS_STATUS_TRYAGAIN;
++		      goto out;
++		    }
++		  line = newline;
++		  linelen = newlinelen;
++		  line_use_malloc = true;
++		}
++	      else
++		{
++		  line = extend_alloca (line, linelen, newlinelen);
++		  alloca_used += newlinelen;
++		}
++	    }
++
++	  /* Copy and find beginning.  */
++	  char *p = memcpy (line, value.data, value.size);
++	  while (isspace (*p))
++	    ++p;
++
++	  struct group grp;
++	  while ((err = _nss_files_parse_grent (p, &grp, buffer, buflen,
++						errnop)) == -1)
++	    {
++	      size_t newbuflen = MAX (2 * buflen, value.size);
++	      if (buffer_use_malloc 
++		  || ! __libc_use_alloca (alloca_used + newbuflen))
++		{
++		  void *newbuf = realloc (buffer_use_malloc ? buffer : NULL,
++					  newbuflen);
++		  if (newbuf == NULL)
++		    {
++		      *errnop = ENOMEM;
++		      status = NSS_STATUS_TRYAGAIN;
++		      goto out;
++		    }
++		  buffer = newbuf;
++		  buflen = newbuflen;
++		  buffer_use_malloc = true;
++		}
++	      else
++		{
++		  buffer = extend_alloca (buffer, buflen, newbuflen);
++		  alloca_used += newbuflen;
++		}
++	    }
++
++	  if (err > 0 && grp.gr_gid != group)
++	    for (char **m = grp.gr_mem; *m != NULL; ++m)
++	      if (strcmp (*m, user) == 0)
++		{
++		  /* Matches user.  Insert this group.  */
++		  if (*start == *size)
++		    {
++		      /* Need a bigger buffer.  */
++		      if (limit > 0 && *size == limit)
++			/* We reached the maximum.  */
++			goto out;
++
++		      long int newsize;
++		      if (limit <= 0)
++			newsize = 2 * *size;
++		      else
++			newsize = MIN (limit, 2 * *size);
++
++		      gid_t *newgroups = realloc (groups,
++						  newsize * sizeof (*groups));
++		      if (newgroups == NULL)
++			{
++			  *errnop = ENOMEM;
++			  status = NSS_STATUS_TRYAGAIN;
++			  goto out;
++			}
++		      *groupsp = groups = newgroups;
++		      *size = newsize;
++		    }
++
++		  groups[*start] = grp.gr_gid;
++		  *start += 1;
++		  
++		  break;
++		}
++	}
++
++    out:
++      if (buffer_use_malloc)
++	free (buffer);
++      if (line_use_malloc)
++	free (line);
++
++      internal_endent (&db, &dbenv);
++    }
++
++  return status;
++}
+--- a/src/Makefile.am.initgr	2011-04-21 13:43:11.698540000 -0400
++++ b/src/Makefile.am	2011-04-21 14:12:27.750429000 -0400
+@@ -11,14 +11,15 @@ localedir = $(datadir)/locale
+ 
+ noinst_HEADERS = db-compat.h netgroup.h nss_db.h
+ 
+-INCLUDES = @DB_CFLAGS@ -D_GNU_SOURCE \
++INCLUDES = @DB_CFLAGS@ -D_GNU_SOURCE -std=gnu99 \
+ 	-I../intl -DLOCALEDIR=\"$(localedir)\"
+ 
+ EXTRA_DIST = libnss_db.map
+ 
+ slib_LTLIBRARIES = libnss_db.la
+ libnss_db_la_SOURCES = db-alias.c db-ethers.c db-netgrp.c db-grp.c db-proto.c \
+-	db-pwd.c db-rpc.c db-service.c db-spwd.c db-compat.c db-open.c
++	db-pwd.c db-rpc.c db-service.c db-spwd.c db-compat.c db-open.c \
++	db-initgroups.c
+ EXTRA_libnss_db_la_SOURCES = libnss_db.map db-XXX.c \
+ 	files-ethers.c files-grp.c files-parse.c files-proto.c files-pwd.c \
+ 	files-rpc.c files-service.c files-spwd.c
+--- a/src/nss_db.h.initgr	2011-04-21 13:37:16.346212000 -0400
++++ b/src/nss_db.h	2011-04-21 14:22:05.644573000 -0400
+@@ -31,4 +31,25 @@ extern enum nss_status internal_setent (
+ /* Close the database *DBP.  */
+ extern void internal_endent (DB **dbp, DB_ENV **dbenvp);
+ 
++
++/* The following are defined in glibc in include/alloca.h.  */
++extern int __libc_alloca_cutoff (size_t size) __attribute__ ((const));
++#define PTHREAD_STACK_MIN 16384
++#define __libc_use_alloca(size) \
++  (__builtin_expect ((size) <= PTHREAD_STACK_MIN / 4, 1)		      \
++		     || __libc_alloca_cutoff (size))
++#if defined __i386__ || defined __x86_64__
++# define extend_alloca(buf, len, newlen) \
++  (__typeof (buf)) ({ size_t __newlen = (newlen);			      \
++                      char *__newbuf = alloca (__newlen);		      \
++                      if (__newbuf + __newlen == (char *) buf)		      \
++                        len += __newlen;				      \
++                      else						      \
++                        len = __newlen;					      \
++                      __newbuf; })
++#else
++# define extend_alloca(buf, len, newlen) \
++  alloca (((len) = (newlen)))
++#endif
++
+ #endif	/* nss_db.h */
+--- a/src/libnss_db.map.initgr	2011-04-26 15:31:20.775659000 -0400
++++ b/src/libnss_db.map	2011-04-26 15:31:42.134332000 -0400
+@@ -14,6 +14,7 @@
+     _nss_db_setaliasent; _nss_db_setetherent; _nss_db_setgrent;
+     _nss_db_setnetgrent; _nss_db_setprotoent; _nss_db_setpwent;
+     _nss_db_setrpcent; _nss_db_setservent; _nss_db_setspent;
++    _nss_db_initgroups_dyn;
+   local:
+     *;
+ };
diff --git a/nss_db.spec b/nss_db.spec
index a50962d..627abbe 100644
--- a/nss_db.spec
+++ b/nss_db.spec
@@ -4,7 +4,7 @@
 Summary: An NSS library for the Berkeley DB
 Name: nss_db
 Version: 2.2.3
-Release: 0.4.pre1%{?dist}
+Release: 0.5.pre1%{?dist}
 Source: ftp://sources.redhat.com/pub/glibc/old-releases/nss_db-%{version}pre1.tar.gz
 Source1: http://download.oracle.com/berkeley-db/db-%{db_version}.tar.gz
 Source2: db-getent-Makefile
@@ -22,6 +22,7 @@ Patch9: nss_db-2.2-lib64.patch
 Patch10: nss_db-2.2-glibc.patch
 Patch11: nss_db-2.2-makedb-atomic.patch
 Patch12: 200-set-db-environment.patch
+Patch13: d-nss_db-initgr.patch
 Patch100: db-4.6.18-glibc.patch
 Patch101: http://www.oracle.com/technology/products/berkeley-db/db/update/4.6.21/patch.4.6.21.1
 Patch102: http://www.oracle.com/technology/products/berkeley-db/db/update/4.6.21/patch.4.6.21.2
@@ -66,6 +67,7 @@ pushd src
 %patch11 -p1 -b .makedb-atomic
 popd
 %patch12 -p1 -b .set-db-environment
+%patch13 -p1 -b .initgr
 cp %{_datadir}/gettext/config.rpath .
 rm -f config.guess config.sub ltmain.sh
 autoreconf -i
@@ -137,6 +139,12 @@ rm -rf ${RPM_BUILD_ROOT}
 %config(noreplace) /var/db/Makefile
 
 %changelog
+* Wed May 18 2011 Nalin Dahyabhai <nalin at redhat.com> - 2.2.3-0.5.pre1
+- import patch to handle initgroups directly rather than forcing libc to
+  use the enumeration interfaces, which could result in two threads calling
+  initgroups() at the same time to both get a subset of the right answers
+  (#705466)
+
 * Tue Feb 08 2011 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 2.2.3-0.4.pre1
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
 


More information about the scm-commits mailing list