From nobody@FreeBSD.org  Thu Feb 15 19:08:20 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 2174216A401
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 15 Feb 2007 19:08:20 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [69.147.83.33])
	by mx1.freebsd.org (Postfix) with ESMTP id 053A613C474
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 15 Feb 2007 19:08:20 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id l1FJ8H0N058335
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 15 Feb 2007 19:08:17 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id l1FJ8HAN058334;
	Thu, 15 Feb 2007 19:08:17 GMT
	(envelope-from nobody)
Message-Id: <200702151908.l1FJ8HAN058334@www.freebsd.org>
Date: Thu, 15 Feb 2007 19:08:17 GMT
From: Gerd Rausch<gerd@juniper.net>
To: freebsd-gnats-submit@FreeBSD.org
Subject: setgroups with incomplete list if line exceeds 1kB
X-Send-Pr-Version: www-3.0

>Number:         109206
>Category:       kern
>Synopsis:       initgroups(3) with incomplete list if line exceeds 1kB
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Feb 15 19:10:05 GMT 2007
>Closed-Date:    Sat Mar 24 02:07:01 GMT 2007
>Last-Modified:  Sat Mar 24 02:07:01 GMT 2007
>Originator:     Gerd Rausch
>Release:        6.1
>Organization:
Juniper Networks
>Environment:
>Description:
This is a bug in libc not handling group lines that exceed 1kB in size
correctly.

The group parsing functions start with a 1k buffer and increase it if
there is need for more space in order to accommodate a line.

Unfortunately, they do not reposition the file pointer so that when
trying to read the line again with an increased buffer size , the
groups that were supposed to be inclueded for a user did not get
picked up.

Fix is to re-position the stream if a situation occurs that we need
more space (i.e. errno == ERANGE).

>How-To-Repeat:

>Fix:


Patch attached with submission follows:

Index: lib/libc/gen/getgrent.c
===================================================================
RCS file: /cvs/junos-2001/src/lib/libc/gen/getgrent.c,v
retrieving revision 1.3.68.2
diff -u -p -r1.3.68.2 getgrent.c
--- lib/libc/gen/getgrent.c	24 Jun 2006 02:58:49 -0000	1.3.68.2
+++ lib/libc/gen/getgrent.c	14 Feb 2007 23:55:31 -0000
@@ -446,6 +446,8 @@ files_group(void *retval, void *mdata, v
 	char			*buffer;
 	size_t			 bufsize, linesize;
 	int			 rv, stayopen, *errnop;
+	fpos_t			 saved_pos;
+	int			 have_saved_pos;
 
 	name = NULL;
 	gid = (gid_t)-1;
@@ -481,7 +483,10 @@ files_group(void *retval, void *mdata, v
 		stayopen = st->stayopen;
 	}
 	rv = NS_NOTFOUND;
-	while ((line = fgetln(st->fp, &linesize)) != NULL) {
+	while (1) {
+		have_saved_pos = fgetpos(st->fp, &saved_pos) == 0;
+		if ((line = fgetln(st->fp, &linesize)) == NULL)
+			break;
 		if (line[linesize-1] == '\n')
 			linesize--;
 		rv = __gr_match_entry(line, linesize, how, name, gid);
@@ -503,6 +508,12 @@ files_group(void *retval, void *mdata, v
 		if (rv & NS_TERMINATE)
 			break;
 	}
+	if (rv == NS_RETURN && *errnop == ERANGE) {
+		if (!have_saved_pos || fsetpos(st->fp, &saved_pos) != 0) {
+			*errnop = ESPIPE;
+			rv = NS_UNAVAIL;
+		}
+	}
 	if (!stayopen && st->fp != NULL) {
 		fclose(st->fp);
 		st->fp = NULL;
@@ -908,6 +919,8 @@ compat_group(void *retval, void *mdata, 
 	void			*discard;
 	size_t			 bufsize, linesize;
 	int			 rv, stayopen, *errnop;
+	fpos_t			 saved_pos;
+	int			 have_saved_pos;
 
 #define set_lookup_type(x, y) do { 				\
 	int i;							\
@@ -1010,7 +1023,10 @@ docompat:
 		break;
 	}
 	rv = NS_NOTFOUND;
-	while ((line = fgetln(st->fp, &linesize)) != NULL) {
+	while (1) {
+		have_saved_pos = fgetpos(st->fp, &saved_pos) == 0;
+		if ((line = fgetln(st->fp, &linesize)) == NULL)
+			break;
 		if (line[linesize-1] == '\n')
 			linesize--;
 		if (linesize > 2 && line[0] == '+') {
@@ -1051,6 +1067,12 @@ docompat:
 		if (rv & NS_TERMINATE)
 			break;
 	}
+	if (rv == NS_RETURN && *errnop == ERANGE) {
+		if (!have_saved_pos || fsetpos(st->fp, &saved_pos) != 0) {
+			*errnop = ESPIPE;
+			rv = NS_UNAVAIL;
+		}
+	}
 fin:
 	if (!stayopen && st->fp != NULL) {
 		fclose(st->fp);

>Release-Note:
>Audit-Trail:

From: gerd@juniper.net
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: misc/109206: setgroups with incomplete list if line exceeds 1kB
Date: Thu, 15 Feb 2007 11:23:37 -0800 (PST)

 Hi,
 
 I realized I made a booboo with regards to the PR:
 
 It should have been called "initgroups with incomplete list..."
 
 Of course, the system call setgroups is not affected by this.
 
 Thanks,
 
   Gerd
State-Changed-From-To: open->feedback 
State-Changed-By: maxim 
State-Changed-When: Thu Feb 15 19:52:20 UTC 2007 
State-Changed-Why:  
I believe, I've already fixed this issue in HEAD and RELENG_6 
(getgrent.c rev. 1.32.8.3).  Please report back it it works for you. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=109206 
State-Changed-From-To: feedback->closed 
State-Changed-By: maxim 
State-Changed-When: Sat Mar 24 02:06:33 UTC 2007 
State-Changed-Why:  
Feedback timeout. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=109206 
>Unformatted:
