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

Bug#403709: nss_compat: infinite retrying of read errors



Package: libc6
Version: 2.3.2.ds1-22sarge4
Severity: minor

Due to a recent power failure, my /etc/shadow file morphed into a directory.
You can probably guess that this made it difficult to log in. You might not
guess the symptom: instead of reporting an authentication failure in the
normal way, any attempt to log in causes a long pause with lots of disk
activity. That's because getspnam() gets stuck in an infinite loop allocating
memory and ends up swapping. No one expected the Spanish Inquisition^W^W^W^H
an EISDIR on /etc/shadow.

After poking around the source a bit, and recreating the incident in a
chroot, I suspect but haven't proven that the cause is in
compat-spwd.c:getspent_next_file which returns NSS_STATUS_TRYAGAIN in case of
read error. What exactly is NSS_STATUS_TRYAGAIN supposed to mean? Apparently
in this case it means "try again as many times as you can, as fast as you
can".

Oh, I just got an idea for another test: fgetspent. And it does the same
infinite memory-eating thing, in spite of not using NSS at all!

#include <stdio.h>
#include <shadow.h>

int main(void)
{
  FILE *fp;
  struct spwd *sp;
  fp=fopen(".", "r");
  if(!fp) {
    perror("fopen(.)");
    return 1;
  }
  sp=fgetspent(fp);
  return 0;
}

Also bombs with fgetpwent and fgetgrent. I suspect it'll do the same with any
read error, not just EISDIR. They all get translated to ERANGE for some
reason, which is then taken as meaning "You need to malloc some more and try
again". Ouch.

nss_files seems to be the only one who got this right.


-- System Information:
Debian Release: 3.1
Architecture: powerpc (ppc)
Kernel: Linux 2.6.17.6
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages libc6 depends on:
ii  libdb1-compat                 2.1.3-7    The Berkeley database routines [gl

-- no debconf information



Reply to: