Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 25 Oct 2011 16:27:38 -0500
From:      Dan Nelson <dnelson@allantgroup.com>
To:        "Christopher J. Ruwe" <cjr@cruwe.de>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: _SC_GETPW_R_SIZE_MAX undefined in sysconf.c, what is correct value?
Message-ID:  <20111025212738.GJ93709@dan.emsphone.com>
In-Reply-To: <20111025220725.7327fd57@dijkstra>
References:  <20111023235231.71f73ea3@dijkstra> <20111024001034.GE93709@dan.emsphone.com> <20111024213140.491467d9@dijkstra> <20111024204209.GF93709@dan.emsphone.com> <20111025220725.7327fd57@dijkstra>

next in thread | previous in thread | raw e-mail | index | archive | help
In the last episode (Oct 25), Christopher J. Ruwe said:
> On Mon, 24 Oct 2011 15:42:10 -0500
> Dan Nelson <dnelson@allantgroup.com> wrote:
> > In the last episode (Oct 24), Christopher J. Ruwe said:
> > > On Sun, 23 Oct 2011 19:10:34 -0500
> > > Dan Nelson <dnelson@allantgroup.com> wrote:
> > > > In the last episode (Oct 23), Christopher J. Ruwe said:
> > > > > I need to get the maximum size of an pwd-entry to determine the
> > > > > correct buffersize for calling getpwnam_r("uname",&pwd, buf,
> > > > > bufsize, &pwdp).  I would like to use
> > > > > sysconf(_SC_GETPW_R_SIZE_MAX) to determine bufsize, which
> > > > > unfornutately fails (returns -1).  Currently, I used 16384,
> > > > > which seems to be too much, bit works for the time being.
> > [..]
> > > > From looking at the libc/gen/getpwent.c file, it looks like a
> > > > maximum size might be 1MB.  The wrapper functions that convert
> > > > getpw*_r functions into ones that simply return a pointer to
> > > > malloced data all use the getpw() helper function, which starts with
> > > > a 1k buffer and keeps doubling its size until the data fits or it
> > > > hits PWD_STORAGE_MAX (1MB).  PWD_STORAGE_MAX is only checked within
> > > > that getpw() function, though, so it's possible that an nss library
> > > > might return an even longer string to a get*_r call.  It's up to you
> > > > to decide what your own limit is :)
> > >
> > > Uh ... it's just that I hoped I had not to decide ;-)
> > 
> > The getpwnam_r function needs enough space to store the "struct passwd"
> > itself (which has a constant size) plus the strings pointed to by
> > pw_name, pw_class, pw_gecos, pw_dir, and pw_shell.  If you have enough
> > control over your environment that you can guarantee that the sum of
> > those strings won't be larger than 4k, then you can just used a fixed
> > buffer of that size.  Even 1k is probably large enough for 99.999% of
> > all systems.  That's a really long home directory or shell path :) On
> > the other hand, the GECOS field is theoretially free-form and could
> > contain a lot of data.  I've never see it hold more than an office
> > number myself, though.
> > 
> 
> Thanks for your help so far. Just assuming (I am not sufficiently clear
> about myself and my own intents) I want to be precise and am afraid of
> guessing: Can I assume that the gecos field is an entry in /etc/passwd and
> can therefore never exceed LINE_MAX, i.e., 2048B (limits.h, line 72)?  Or,
> more precisely, ( 2048B - sum( lenght(all fields except passwd) ) )? 
> Would that be an acceptable limit to set the getpwnam_r( ...  ) buffer to
> and/or would that be an acceptable value to replace the following bit from
> sysconf.c?
> 
>     372	   #if _POSIX_THREAD_SAFE_FUNCTIONS > -1
>     373 	case _SC_GETGR_R_SIZE_MAX:
>     374 	case _SC_GETPW_R_SIZE_MAX:
>     375 	#error "somebody needs to implement this"
>     376    #endif

If your nsswitch.conf has "passwd: files" in it, then yes, you can assume
that the 2048-byte limit applies.  However, if you are using nss_ldap,
nss_mysql, nss_winbind, or some other nsswitch module that provides user
info, that backend user system may be capable of returning longer strings. 
If you want to be able to handle any struct passwd that might be thrown at
you, you should implement a "retry with doubling" loop similar to the one in
libc/gen/getpwent.c:getpw() .
 
-- 
	Dan Nelson
	dnelson@allantgroup.com



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111025212738.GJ93709>