svn commit: r192087 - in projects/ngroups: lib/libc/gen lib/libc/rpc lib/libc/sys usr.bin/id usr.bin/newgrp usr.bin/quota usr.sbin/chown usr.sbin/chroot usr.sbin/jail usr.sbin/jexec usr.sbin/lpr/lpc

Bruce Evans bde at zeta.org.au
Fri May 29 11:02:09 UTC 2009


On Thu, 28 May 2009, Brooks Davis wrote:

> On Fri, May 15, 2009 at 01:32:52PM +1000, Bruce Evans wrote:
>> On Thu, 14 May 2009, Brooks Davis wrote:
>>
>>> Log:
>>>  Use to value returned by sysconf(_SC_NGROUPS_MAX) in favor of
>>>  NGROUPS_MAX or NGROUPS since POSIX says that NGROUPS_MAX represents a
>>>  lower bound on sysconf(_SC_NGROUPS_MAX).
>>
>> Actually, POSIX says that NGROUPS_MAX is identical to
>> sysconf(_SC_NGROUPS_MAX) if it is defined (and the sysconf() succeeds).
>> It is _POSIX_NGROUPS_MAX that gives the lower bound.  _POSIX_NGROUPS_MAX
>> is always 8, except under old versions of POSIX that don't require
>> supplementary groups to be supported, where it is always 0.  It is a
>> bug for a POSIX implementation to define NGROUPS_MAX if its value is
>> not always identical to sysconf(_SC_NGROUPS_MAX), or for a POSIX
>> application to use NGROUPS_MAX unconditionally.
>
> According to the limits.h section of POSIX.1-2008, NGROUPS_MAX is a
> Runtime Increasable Value and thus NGROUPS_MAX specifies the minimum
> value that implementation may use.

Gak, so it is.  This makes the compile-time constant value NGROUPS_MAX
(or any Runtime Increasable Value) almost useless in applications,
since it is always defined but only gives the minimum value (for a
"specific" implementation, whatever that is).  NGROUPS_MAX can be used
to allocate storage for functions like getgroups(2), but then the function
will fail if the minimum value is smaller than the maximum and the calling
process actually belongs to more than the minimum number of groups.
Recovering from such failures would be harder (e.g., by trying again
after doubling the allocation size) would be harder than avoiding the
failure (by allocating enough storage using sysconf() to determine the
amount needed).  OTOH, the most efficient way might be to always allocate
a large amount of storage initially (say PAGE_SIZE) and never look at
{NGROUPS_MAX}.

In POSIX.1-1990, {NGROUPS_MAX} is the _only_ Runtime Increasable Value.
In POSIX.1-2001, there are lots more, but they are mainly for userland
limits like {LINE_MAX} whose existence is a much larger bug than that of
{NGROUPS_MAX}.

> Given the constraint that the value
> returned by sysconf(_SC_NGROUPS_MAX) not change during the life of a
> process, there is probably a practical limitation that the underlying
> limit be controllable at compile time or by a tunable, but not by sysctl.

No one worries about sysctl()s and setrlimit()s breaking this constraint
for other limits, but POSIX recently) added words to specify exactly how
setting RLIMIT_NOFILE breaks^Waffects {OPEN_MAX}.

> I'll look over and incorporate your other comments shortly.

They were mainly about localizing the allocating of group lists.  It
would be harder to localize the more general allocation algorithms
described above -- doubling the allocation size after it is found to
be too small seems to need at least a separate loop for each function
that detects the failure.  I actually thought of such interfaces when
I wrote the old mail -- use interfaces that allocate the storage
internally, like asprintf().  getgrouplist() would be suitable for
this treatment, and wouldn't even need to be renamed (it would allocate
the storage iff its groups parameter is NULL).  Syscalls couldn't do
this, but getgroups(2) could become agetgroups(3).

Bruce


More information about the svn-src-projects mailing list