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

Bug#557596: gaih_inet logic for summarizing gethostbyname4_r results broken



Package: eglibc
Version: 2.10.1-7
Severity: important
Tags: patch

NSS plugins wishing to provide data to programs calling getaddrinfo() must
implement two procedures named:
   _nss_<foo>_gethostbyname4_r() and
   _nss_<foo>_gethostbyname2_r().

The function gaih_inet() in libc dynamically loads and calls these procedures
and then attempts to combine the results from all available plugins.

Unfortunately, in the following scenario, the combination step is performed
incorrectly:

  1. Install your NSS plugin so that it is called after the
     libnss_dns-2.10.1.so plugin.

2. Remove your default route.
  3. Call getaddrinfo(NODE, SERVICE, NULL, &results).
The problem is that the third call, internally, results in a call to
  _nss_dns_gethostbyname4_r()

which returns NSS_STATUS_UNAVAIL with herrno = TRY_AGAIN. This combination of
return and error codes causes gaih_inet()'s logic to set
  no_data = -3.

This variable is used to signal to the rest of the gaih_inet procedure that no
results are available.

Unfortunately, when your plugin returns NSS_STATUS_SUCCESS and sets herrno =
NETDB_SUCCESS, your plugin's results will be *ignored* because gaih_inet
exits its loop without resetting no_data.

The attached patch fixes the problem for me. The patch was tested with code
from http://wiki.laptop.org/go/Dnshash.

-- System Information:
Debian Release: squeeze/sid
  APT prefers stable
  APT policy: (700, 'stable'), (600, 'unstable'), (500, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.30-2-686 (SMP w/1 CPU core)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
--- a/sysdeps/posix/getaddrinfo.c       2009-11-22 16:21:19.000000000 -0500
+++ b/sysdeps/posix/getaddrinfo.c       2009-11-22 16:28:26.000000000 -0500
@@ -715,7 +715,10 @@ gaih_inet (const char *name, const struc
                                                   tmpbuflen, &rc, &herrno,
                                                   NULL));
                      if (status == NSS_STATUS_SUCCESS)
-                       break;
+                       {
+                         no_data = 0;
+                         break;
+                       }
                      if (status != NSS_STATUS_TRYAGAIN
                          || rc != ERANGE || herrno != NETDB_INTERNAL)
                        {


Reply to: