From kwebb@flux.utah.edu  Fri May  5 22:31:16 2006
Return-Path: <kwebb@flux.utah.edu>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 91ED016A401
	for <FreeBSD-gnats-submit@freebsd.org>; Fri,  5 May 2006 22:31:16 +0000 (UTC)
	(envelope-from kwebb@flux.utah.edu)
Received: from bas.flux.utah.edu (bas.flux.utah.edu [155.98.60.2])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 3B34E43D45
	for <FreeBSD-gnats-submit@freebsd.org>; Fri,  5 May 2006 22:31:16 +0000 (GMT)
	(envelope-from kwebb@flux.utah.edu)
Received: from vodka.flux.utah.edu (vodka.flux.utah.edu [155.98.60.36])
	by bas.flux.utah.edu (8.12.11/8.12.11) with ESMTP id k45MVF6m084617
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 5 May 2006 16:31:15 -0600 (MDT)
	(envelope-from kwebb@flux.utah.edu)
Received: from vodka.flux.utah.edu (localhost [127.0.0.1])
	by vodka.flux.utah.edu (8.13.4/8.13.4) with ESMTP id k45MVFqF058232
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 5 May 2006 16:31:15 -0600 (MDT)
	(envelope-from kwebb@vodka.flux.utah.edu)
Received: (from kwebb@localhost)
	by vodka.flux.utah.edu (8.13.4/8.13.4/Submit) id k45MVFTB058231;
	Fri, 5 May 2006 16:31:15 -0600 (MDT)
	(envelope-from kwebb)
Message-Id: <200605052231.k45MVFTB058231@vodka.flux.utah.edu>
Date: Fri, 5 May 2006 16:31:15 -0600 (MDT)
From: Kirk Webb <kwebb@flux.utah.edu>
Reply-To: Kirk Webb <kwebb@flux.utah.edu>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] getgrent() does not return large groups via NIS
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         96840
>Category:       bin
>Synopsis:       [libc] [patch] getgrent() does not return large groups via NIS
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-bugs
>State:          analyzed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri May 05 22:40:14 GMT 2006
>Closed-Date:    
>Last-Modified:  Mon Mar  3 18:10:00 UTC 2014
>Originator:     Kirk Webb <kwebb@flux.utah.edu>
>Release:        FreeBSD 6.0-RELEASE-p6 i386
>Organization:
University of Utah
>Environment:
System: FreeBSD vodka 6.0-RELEASE-p6 FreeBSD 6.0-RELEASE-p6 #0: Fri Apr 7 15:13:12 MDT 2006 root@vodka:/usr/obj/z/src/sys/DESKTOP i386

>Description:

The nis_groups() function in src/lib/libc/gen/getgrent.c skips groups
with a large number of members and/or large number of total characters
in the membership list when fetching from NIS.  Thus, anything using
or vectoring through getgrent() (e.g. initgroups() and getgrouplist())
will not see these groups.  getgrent_r is also affected, although the
caller may pass in a larger buffer and so avoid the problem.  The most
obviously problematic side-effect of this behavior is that users end
up with groups missing from their groups list, and so have
reduced/incorrect permissions.

>How-To-Repeat:

Add something like the following group line to an NIS server with a
FreeBSD client, with a legitimate user placed somewhere in the list
(just make sure the member list is long):

footest:*:6666:f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30,f31,f32,f33,f34,f35,f36,f37,f38,f39,f40,f41,f42,f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65,f66,f67,f68,f69,f70,f71,f72,f73,f74,f75,f76,f77,f78,f79,f80,f81,f82,f83,f84,f85,f86,f87,f88,f89,f90,f91,f92,f93,f94,f95,f96,f97,f98,f99,f100,f101,f102,f103,f104,f105,f106,f107,f108,f109,f110,f111,f112,f113,f114,f115,f116,f117,f118,f119,f120,f121,f122,f123,f124,f125,f126,f127,f128,f129

Next, go to a FreeBSD 6 client bound to this server and execute
'groups' or 'id' for the user.  The test list should be missing.

Now remove half or so of the above entries, but keep the legit user,
and rebuild the server's yp database.  Execute 'groups' or 'id' against the
user on the FreeBSD 6 client and the test group should show up.

>Fix:

The included patch should do the trick.  The problem is that
nis_group() does not check for an ERANGE error code when coming back
from __gr_parse_entry().  Rather, it just summarily continues on
through the loop and tries to grab the next entry.

This patch works by saving the old NIS key in the NIS state structure
rather than replacing it immediately with the new key.  The new key is
saved off so long as an ERANGE is not encountered by
__gr_parse_entr().  If this happens, the "erange" trapdoor is taken
out of nis_group().  I tried to be careful with memory
allocation/dealloc, but a careful scan from a second (or more) set of
eyes is always a good idea.

The patch below should apply cleanly to the HEAD for file 
src/lib/libc/getgrent.c

--- getgrent.c.diff begins here ---
--- getgrent.c	Fri May  5 15:46:28 2006
+++ /usr/src/lib/libc/gen/getgrent.c	Fri May  5 15:44:13 2006
@@ -967,7 +967,6 @@
 	int		*errnop, keylen, resultlen, rv;
 	
 	name = NULL;
-        key  = NULL;
 	gid = (gid_t)-1;
 	how = (enum nss_lookup_type)mdata;
 	switch (how) {
@@ -1017,16 +1016,19 @@
 		result = NULL;
 		if (how == nss_lt_all) {
 			if (st->key == NULL)
-				rv = yp_first(st->domain, map, &key,
-				    &keylen, &result, &resultlen);
+				rv = yp_first(st->domain, map, &st->key,
+				    &st->keylen, &result, &resultlen);
 			else {
-				rv = yp_next(st->domain, map, 
-                                    st->key, st->keylen,
-                                    &key, &keylen, &result, &resultlen);
+				key = st->key;
+				keylen = st->keylen;
+				st->key = NULL;
+				rv = yp_next(st->domain, map, key, keylen,
+				    &st->key, &st->keylen, &result,
+				    &resultlen);
+				free(key);
 			}
 			if (rv != 0) {
 				free(result);
-                                free(key);
 				free(st->key);
 				st->key = NULL;
 				if (rv == YPERR_NOMORE) {
@@ -1052,35 +1054,16 @@
 		 * terminator, alignment padding, and one (char *)
 		 * pointer for the member list terminator.
 		 */
-		if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *)) {
-                        if (how == nss_lt_all) {
-                                free(key);
-                        }
-                        goto erange;
-                }
+		if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *))
+			goto erange;
 		memcpy(buffer, result, resultlen);
 		buffer[resultlen] = '\0';
 		free(result);
 		rv = __gr_match_entry(buffer, resultlen, how, name, gid);
-		if (rv == NS_SUCCESS) {
+		if (rv == NS_SUCCESS)
 			rv = __gr_parse_entry(buffer, resultlen, grp,
 			    &buffer[resultlen+1], bufsize - resultlen - 1,
 			    errnop);
-                        if (*errnop == ERANGE) {
-                                if (how == nss_lt_all) {
-                                        free(key);
-                                }
-                                goto erange;
-                        }
-                }
-                if (how == nss_lt_all) {
-                        if (st->key != NULL) {
-                                free(st->key);
-                        }
-                        st->key = key;
-                        st->keylen = keylen;
-                        key = NULL;
-                }
 	} while (how == nss_lt_all && !(rv & NS_TERMINATE));
 fin:
 	if (rv == NS_SUCCESS && retval != NULL)
--- getgrent.c.diff ends here ---


>Release-Note:
>Audit-Trail:
Adding to audit trail from misfiled PR kern/96841:

 Oops... I submitted the patch reversed.  Sorry!  Here is the corrected 
 version:
 
 --- /usr/src/lib/libc/gen/getgrent.c	Fri May  5 15:44:13 2006
 +++ getgrent.c	Fri May  5 15:46:28 2006
 @@ -967,6 +967,7 @@
  	int		*errnop, keylen, resultlen, rv;
  	
  	name = NULL;
 +        key  = NULL;
  	gid = (gid_t)-1;
  	how = (enum nss_lookup_type)mdata;
  	switch (how) {
 @@ -1016,19 +1017,16 @@
  		result = NULL;
  		if (how == nss_lt_all) {
  			if (st->key == NULL)
 -				rv = yp_first(st->domain, map, &st->key,
 -				    &st->keylen, &result, &resultlen);
 +				rv = yp_first(st->domain, map, &key,
 +				    &keylen, &result, &resultlen);
  			else {
 -				key = st->key;
 -				keylen = st->keylen;
 -				st->key = NULL;
 -				rv = yp_next(st->domain, map, key, keylen,
 -				    &st->key, &st->keylen, &result,
 -				    &resultlen);
 -				free(key);
 +				rv = yp_next(st->domain, map, 
 +                                    st->key, st->keylen,
 +                                    &key, &keylen, &result, &resultlen);
  			}
  			if (rv != 0) {
  				free(result);
 +                                free(key);
  				free(st->key);
  				st->key = NULL;
  				if (rv == YPERR_NOMORE) {
 @@ -1054,16 +1052,35 @@
  		 * terminator, alignment padding, and one (char *)
  		 * pointer for the member list terminator.
  		 */
 -		if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *))
 -			goto erange;
 +		if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *)) {
 +                        if (how == nss_lt_all) {
 +                                free(key);
 +                        }
 +                        goto erange;
 +                }
  		memcpy(buffer, result, resultlen);
  		buffer[resultlen] = '\0';
  		free(result);
  		rv = __gr_match_entry(buffer, resultlen, how, name, gid);
 -		if (rv == NS_SUCCESS)
 +		if (rv == NS_SUCCESS) {
  			rv = __gr_parse_entry(buffer, resultlen, grp,
  			    &buffer[resultlen+1], bufsize - resultlen - 1,
  			    errnop);
 +                        if (*errnop == ERANGE) {
 +                                if (how == nss_lt_all) {
 +                                        free(key);
 +                                }
 +                                goto erange;
 +                        }
 +                }
 +                if (how == nss_lt_all) {
 +                        if (st->key != NULL) {
 +                                free(st->key);
 +                        }
 +                        st->key = key;
 +                        st->keylen = keylen;
 +                        key = NULL;
 +                }
  	} while (how == nss_lt_all && !(rv & NS_TERMINATE));
  fin:
  	if (rv == NS_SUCCESS && retval != NULL)

From: "Andrey Zonov" <andrey.zonov@gmail.com>
To: bug-followup@FreeBSD.org, kwebb@flux.utah.edu
Cc:  
Subject: Re: bin/96840: [libc] [patch] getgrent() does not return large groups via NIS
Date: Mon, 19 Jan 2009 16:57:32 +0300

 ------=_Part_12133_18295628.1232373452568
 Content-Type: text/plain; charset=ISO-8859-1
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 Hi,
 
 I encountered with bug again in last month.
 This patch (reversed) help me. Thx.
 Why this patch in not HEAD?
 
 -- 
 Andrey Zonov
 
 ------=_Part_12133_18295628.1232373452568--
State-Changed-From-To: open->analyzed 
State-Changed-By: linimon 
State-Changed-When: Thu Mar 5 01:44:59 UTC 2009 
State-Changed-Why:  
Another contributor notes that this patch helps. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=96840 

From: Kirk Webb <kwebb@flux.utah.edu>
To: Tim Leamy <tcleamy@ucdavis.edu>
Cc: "bug-followup@FreeBSD.org" <bug-followup@freebsd.org>, "kwebb@flux.utah.edu" <kwebb@flux.utah.edu>
Subject: Re: bin/96840: [libc] [patch] getgrent() does not return large groups
 via NIS
Date: Fri, 28 Feb 2014 15:35:15 -0700

 Oops... Looks like the fix didn't get pulled upstream!  We're moving
 to 9.x soon, so I appreciate the heads up.
 
 -Kirk
 
 
 On Fri, Feb 28, 2014 at 3:28 PM, Tim Leamy <tcleamy@ucdavis.edu> wrote:
 > I just ran across this bug in FreeBSD 9.2 amd64.  The odd thing is that I'm
 > migrating from 8.3 i386 and those systems don't have the issue with the same
 > NIS maps.  So it worked for me on FreeBSD 8.2 i386 & 8.3 i386, but not 9.2
 > amd64.  Go figure.
 >
 >
 >
 > I figured I should email in to push to get this patch added into the
 > releases.  The patch work for me although the line numbers were off by ~120.
 > I guess a bit of code has been added since FreeBSD 6.
 >
 >
 >
 > Tim Leamy
 >
 > UC Davis

From: Tim Leamy <tcleamy@ucdavis.edu>
To: "bug-followup@FreeBSD.org" <bug-followup@FreeBSD.org>,
        "kwebb@flux.utah.edu" <kwebb@flux.utah.edu>
Cc:  
Subject: Re: bin/96840: [libc] [patch] getgrent() does not return large
 groups via NIS
Date: Fri, 28 Feb 2014 22:28:05 +0000

 --_000_05de78c0f15f4c25acfd683e8b994658BY2PR08MB191namprd08pro_
 Content-Type: text/plain; charset="us-ascii"
 Content-Transfer-Encoding: quoted-printable
 
 I just ran across this bug in FreeBSD 9.2 amd64.  The odd thing is that I'm=
  migrating from 8.3 i386 and those systems don't have the issue with the sa=
 me NIS maps.  So it worked for me on FreeBSD 8.2 i386 & 8.3 i386, but not 9=
 .2 amd64.  Go figure.
 
 I figured I should email in to push to get this patch added into the releas=
 es.  The patch work for me although the line numbers were off by ~120.  I g=
 uess a bit of code has been added since FreeBSD 6.
 
 Tim Leamy
 UC Davis
 
 --_000_05de78c0f15f4c25acfd683e8b994658BY2PR08MB191namprd08pro_
 Content-Type: text/html; charset="us-ascii"
 Content-Transfer-Encoding: quoted-printable
 
 <html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
 osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
 xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
 //www.w3.org/TR/REC-html40">
 <head>
 <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dus-ascii"=
 >
 <meta name=3D"Generator" content=3D"Microsoft Word 14 (filtered medium)">
 <style><!--
 /* Font Definitions */
 @font-face
 	{font-family:Calibri;
 	panose-1:2 15 5 2 2 2 4 3 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
 	{margin:0in;
 	margin-bottom:.0001pt;
 	font-size:11.0pt;
 	font-family:"Calibri","sans-serif";}
 a:link, span.MsoHyperlink
 	{mso-style-priority:99;
 	color:blue;
 	text-decoration:underline;}
 a:visited, span.MsoHyperlinkFollowed
 	{mso-style-priority:99;
 	color:purple;
 	text-decoration:underline;}
 span.EmailStyle17
 	{mso-style-type:personal-compose;
 	font-family:"Arial","sans-serif";
 	color:windowtext;}
 .MsoChpDefault
 	{mso-style-type:export-only;
 	font-family:"Calibri","sans-serif";}
 @page WordSection1
 	{size:8.5in 11.0in;
 	margin:1.0in 1.0in 1.0in 1.0in;}
 div.WordSection1
 	{page:WordSection1;}
 --></style><!--[if gte mso 9]><xml>
 <o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
 </xml><![endif]--><!--[if gte mso 9]><xml>
 <o:shapelayout v:ext=3D"edit">
 <o:idmap v:ext=3D"edit" data=3D"1" />
 </o:shapelayout></xml><![endif]-->
 </head>
 <body lang=3D"EN-US" link=3D"blue" vlink=3D"purple">
 <div class=3D"WordSection1">
 <p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:&quot;Ar=
 ial&quot;,&quot;sans-serif&quot;">I just ran across this bug in FreeBSD 9.2=
  amd64.&nbsp; The odd thing is that I&#8217;m migrating from 8.3 i386 and t=
 hose systems don&#8217;t have the issue with the same NIS maps.&nbsp; So it=
  worked
  for me on FreeBSD 8.2 i386 &amp; 8.3 i386, but not 9.2 amd64.&nbsp; Go fig=
 ure.<o:p></o:p></span></p>
 <p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:&quot;Ar=
 ial&quot;,&quot;sans-serif&quot;"><o:p>&nbsp;</o:p></span></p>
 <p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:&quot;Ar=
 ial&quot;,&quot;sans-serif&quot;">I figured I should email in to push to ge=
 t this patch added into the releases.&nbsp; The patch work for me although =
 the line numbers were off by ~120.&nbsp; I guess a bit of code has
  been added since FreeBSD 6.<o:p></o:p></span></p>
 <p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:&quot;Ar=
 ial&quot;,&quot;sans-serif&quot;"><o:p>&nbsp;</o:p></span></p>
 <p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:&quot;Ar=
 ial&quot;,&quot;sans-serif&quot;">Tim Leamy<o:p></o:p></span></p>
 <p class=3D"MsoNormal"><span style=3D"font-size:10.0pt;font-family:&quot;Ar=
 ial&quot;,&quot;sans-serif&quot;">UC Davis&nbsp;
 <o:p></o:p></span></p>
 </div>
 </body>
 </html>
 
 --_000_05de78c0f15f4c25acfd683e8b994658BY2PR08MB191namprd08pro_--
>Unformatted:
