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

Bug#347358: libc6: getent skips IPv4 entries in /etc/hosts



Package: libc6
Version: 2.3.5-11
Severity: normal

If you add the following line to /etc/hosts:

1.2.3.4         x.y.z

getent will not find it:

$ getent hosts 1.2.3.4
$

This happens in both testing and unstable.

The problem seems to be in nss/getent.c:279
      char addr[IN6ADDRSZ];

      if (inet_pton (AF_INET6, key[i], &addr) > 0)
        host = gethostbyaddr (addr, sizeof (addr), AF_INET6);
      else if (inet_pton (AF_INET, key[i], &addr) > 0)
        host = gethostbyaddr (addr, sizeof (addr), AF_INET);
      else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
        host = gethostbyname2 (key[i], AF_INET);

The second call to inet_pton recognizes the queried address as IPv4 but
calls gethostbyaddr with size of 16:

#0  0x400de776 in *__GI_inet_pton (af=2, src=0x804e078 "1.2.3.4", 
    dst=0x804e060) at inet_pton.c:56
#1  0x401341c7 in internal_getent (result=0x4012fe94, 
    buffer=0x804e060 "\200\215\"[ÜÑ\004\bná\004\b", buflen=1024, 
    errnop=0x4012e340, herrnop=0xbffffc88, af=2, flags=8)
    at nss_files/files-hosts.c:50
#2  0x401350ea in _nss_files_gethostbyaddr_r (addr=0xbffffcb4, len=16, af=2, 
    result=0x4012fe94, buffer=0x804e060 "\200\215\"[ÜÑ\004\bná\004\b",
    buflen=1024, errnop=0x4012e340, herrnop=0xbffffc88)
    at nss_files/files-hosts.c:286
#3  0x400e4cc1 in __gethostbyaddr_r (addr=0xbffffcb4, len=16, type=2,
    resbuf=Variable "resbuf" is not available.)
    at getXXbyYY_r.c:207 
#4  0x400e4a00 in gethostbyaddr (addr=0xbffffcb4, len=16, type=2)
    at getXXbyYY.c:116 

Notice that type=2 (AF_INET) but len=16.

Finally this breaks in _nss_files_gethostbyaddr_r:

      while ((status =
              internal_getent (result, buffer, buflen, errnop, herrnop, af,
                               (len == 16 ? 0x0008 : 0))) ==
             NSS_STATUS_SUCCESS)
        {
          {
            if (result->h_length == (int) len
                && !memcmp (addr, result->h_addr_list[0], len))  
              break;
          }
        }

The while loop returns IPv4 entries from /etc/hosts but their length is 4
so the 'result->h_length == (int) len' check will fail and they get skipped.

This code is generated by a macro in nss/nss_files/files-hosts.c:286

DB_LOOKUP (hostbyaddr, ,,
           {
             if (result->h_length == (int) len
                 && ! memcmp (addr, result->h_addr_list[0], len))
               break;
           }, const void *addr, socklen_t len, int af)

Changing the size parameter in the second call to gethostbyaddr 
to either 4 or 'sizeof (struct in_addr)' helps:

      char addr[IN6ADDRSZ];

      if (inet_pton (AF_INET6, key[i], &addr) > 0)
        host = gethostbyaddr (addr, sizeof (addr), AF_INET6);
      else if (inet_pton (AF_INET, key[i], &addr) > 0)
        host = gethostbyaddr (addr, sizeof (in_addr), AF_INET);
      else if ((host = gethostbyname2 (key[i], AF_INET6)) == NULL)
        host = gethostbyname2 (key[i], AF_INET);

Or perhaps gethostbyaddr should check for mismatched af/size parameters?

-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.8-2-686
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

-- no debconf information



Reply to: