Date: Thu, 15 Feb 2007 19:08:17 GMT From: Gerd Rausch<gerd@juniper.net> To: freebsd-gnats-submit@FreeBSD.org Subject: misc/109206: setgroups with incomplete list if line exceeds 1kB Message-ID: <200702151908.l1FJ8HAN058334@www.freebsd.org> Resent-Message-ID: <200702151910.l1FJA5th056849@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200702151908.l1FJ8HAN058334>