This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2][BZ #15339] Avoid returning EAI_SYSTEM when there's a network error


On Mon, Apr 08, 2013 at 09:42:39PM +0400, Dmitry V. Levin wrote:
> The configuration is essentially a bare chroot without additional
> configuration, the kernel is 3.8.6.  send_dg doesn't call sendmmsg because
> of buf2 == NULL.

Aha, so it's AF_INET and not AF_UNSPEC like your original reproducer
suggested.  Here's an updated patch for 15339.  The major difference
here is that I had incorrectly concluded that NSS_STATUS_UNAVAIL
equals to an internal failure.  It's only an internal failure if none
of the services were usable and in that case too, only when the
failure was due to something other than not being able to find the nss
module.  The latter case is implied if NSS_STATUS_UNAVAIL is returned
as is along with h_errno as NO_RECOVERY.

Siddhesh

	[BZ #15339]
	* nss/getXXbyYY_r.c (REENTRANT_NAME): Set NETDB_INTERNAL only
	when no services were used.
	* sysdeps/posix/getaddrinfo.c (gaih_inet): Set h_errno.
	Return EAI_SYSTEM if h_errno is NETDB_INTERNAL.

diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
index 1067744..9e4d110 100644
--- a/nss/getXXbyYY_r.c
+++ b/nss/getXXbyYY_r.c
@@ -284,11 +284,11 @@ done:
 #endif
   *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
 #ifdef NEED_H_ERRNO
-  if (status == NSS_STATUS_UNAVAIL)
-    /* Either we failed to lookup the functions or the functions themselves
-       had a system error.  Set NETDB_INTERNAL here to let the caller know
-       that the errno may have the real reason for failure.  */
-      *h_errnop = NETDB_INTERNAL;
+  if (status == NSS_STATUS_UNAVAIL && !any_service && errno != ENOENT)
+    /* This happens when we weren't able to use a service for reasons other
+       than the module not being found.  In such a case, we'd want to tell the
+       caller that errno has the real reason for failure.  */
+    *h_errnop = NETDB_INTERNAL;
   else if (status != NSS_STATUS_SUCCESS && !any_service)
     /* We were not able to use any service.  */
     *h_errnop = NO_RECOVERY;
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 2309281..2928537 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -1035,7 +1035,14 @@ gaih_inet (const char *name, const struct gaih_service *service,
 			}
 		    }
 		  else
-		    status = NSS_STATUS_UNAVAIL;
+		    {
+		      status = NSS_STATUS_UNAVAIL;
+		      /* Could not load any of the lookup functions.  Indicate
+		         an internal error if the file was found but some other
+		         error led to the failure.  */
+		      if (errno != ENOENT)
+			__set_h_errno (NETDB_INTERNAL);
+		    }
 		}
 
 	      if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
@@ -1049,7 +1056,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
 
 	  _res.options |= old_res_options & RES_USE_INET6;
 
-	  if (status == NSS_STATUS_UNAVAIL)
+	  if (h_errno == NETDB_INTERNAL)
 	    {
 	      result = GAIH_OKIFUNSPEC | -EAI_SYSTEM;
 	      goto free_and_return;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]