[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#553344: libnss-ldapd: errno 34 set



reassign 553344 libc6 2.9-27
retitle 553344 libc6: getgrent() should not pass ERANGE from NSS module with NSS_STATUS_TRYAGAIN
thanks

On Fri, 2009-10-30 at 12:58 +0000, Adrian Bridgett wrote:
> Using the test code attached (to track down what was a bug in
> libnss-ldap), errno is being set after a specific getgrent call.
> 
> There are 214 people in the group, totalling 4164 bytes so this may
> well just be a "too large" error coming back (no other group
> complains, but this is probably the longest group).

Thanks for your bugreport.

I think this is a bug in glibc. What happens is that the buffer that is
used to store the group information is too small to fit all the group
members. The NSS module tells this to glibc by returning
NSS_STATUS_TRYAGAIN and setting errno to ERANGE, see:
http://www.gnu.org/s/libc/manual/html_node/NSS-Modules-Interface.html

Glibc then grows the buffer and calls the NSS module again but the errno
from the first failed call is not cleared. libnss-ldapd only touches the
returned errno if something went wrong (I believe this to be correct
behaviour).

This also happens when a large group is defined in /etc/group so it is
not specific to libnss-ldapd. Note that the buffer is never shrunk so
this only happens on the first call and not on the second run of your
test program.

I think glibc should not pass the errno set by the NSS module to the
user if it was just a mechanism to signal that the buffer should be
grown (and glibc did grow the buffer) or reset errno to the previous
value on retry.

Anyway, attached is a test program that shows the problem a little
clearer. You need a large group (with say 100 members) to test this. In
my test environment this prints:

getgrent(): group "root", 0 members
getgrent(): group "daemon", 0 members
[...]
getgrent(): group "testgroup", 2 members
getgrent(): group "largegroup", 100 members errno=34 ("Numerical result out of range")
getgrent(): group "hugegroup", 1000 members errno=34 ("Numerical result out of range")
getgrent(): group "users", 2 members
getgrent(): group "testgroup2", 2 members

Test performed with both libc6 2.9-27 and 2.10.1-3, nscd not running.

Btw, this may be in some ways related to bug #468378.

-- 
-- arthur - adejong@debian.org - http://people.debian.org/~adejong --
#include <sys/types.h>
#include <grp.h>
#include <stdio.h>
#include <errno.h>

main()
{
  int c;
  struct group * group;
  errno=0;
  while(group=getgrent())
  {
    for (c=0;group->gr_mem[c]!=NULL;c++);
    printf("getgrent(): group \"%s\", %d members",group->gr_name,c);
    if (errno)
      printf(" errno=%d (\"%s\")",errno,strerror(errno));
    printf("\n");
    errno=0;
  }
}

Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: