misc/109206: setgroups with incomplete list if line exceeds 1kB
Gerd Rausch
gerd at juniper.net
Thu Feb 15 19:10:06 UTC 2007
>Number: 109206
>Category: misc
>Synopsis: setgroups with incomplete list if line exceeds 1kB
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Feb 15 19:10:05 GMT 2007
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:
More information about the freebsd-bugs
mailing list