[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

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

  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

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,
                      if (status == NSS_STATUS_SUCCESS)
-                       break;
+                       {
+                         no_data = 0;
+                         break;
+                       }
                      if (status != NSS_STATUS_TRYAGAIN
                          || rc != ERANGE || herrno != NETDB_INTERNAL)

Reply to: