[#958652] Set EAI_SYSTEM only when h_errno is NETDB_INTERNAL
by Siddhesh Poyarekar
Hi,
A patch I had pushed into 2.16 had an error which resulted in the
regression described in the aforementioned bug as well as the bug
described in bz @15339. Attached patch fixes this. If it looks OK,
I'll apply it in rawhide and f19. I have also posted it upstream:
http://sourceware.org/ml/libc-alpha/2013-05/msg00567.html
Siddhesh
commit 69cbe0434e5ddf223ed17141ae9527fb83fde1fa
Author: Siddhesh Poyarekar <siddhesh(a)redhat.com>
Date: Wed May 15 20:06:20 2013 +0530
Set EAI_SYSTEM only when h_errno is NETDB_INTERNAL
Fixes BZ #15339.
NSS_STATUS_UNAVAIL may mean that a necessary input resource is not
available. This could occur in a number of cases including when the
network is down, system runs out of file descriptors, etc. The
correct differentiator in such a case is the h_errno, which gives the
nature of failure. In case of failures other than a simple 'not
found', we set h_errno as NETDB_INTERNAL and let errno be the
identifier for the exact error.
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 d368306..cdd869d 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 != 0 && 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;
10 years, 10 months
[PATCH] BZ#959034 - Fix _nl_find_msg malloc failure case, and callers.
by Carlos O'Donell
This patch fixes two issues, and perhaps should be two distinct patches,
but I present it here as one for the sake of completeness.
This commit:
commit 006dd86111c44572dbd3b26e9c63dd0f834d7762
Author: Jeff Law <law(a)redhat.com>
Date: Thu Jun 21 17:15:38 2012 -0600
[BZ #14277]
* intl/dcigettext.c (_nl_find_msg): Avoid use after potential
free. Simplify list management for _LIBC case.
Fails to check malloc's return in intl/dcigettext.c (_nl_find_msg):
~~~~
freemem_size = INITIAL_BLOCK_SIZE;
newmem = (transmem_block_t *) malloc (freemem_size);
# ifdef _LIBC
/* Add the block to the list of blocks we have to free
at some point. */
newmem->next = transmem_list;
transmem_list = newmem;
~~~
If malloc fails then newmem is NULL then newmem->next results in a fault.
The fix is easy enough, check for newmem != NULL, and fall through to
the error condition below which returns (char *) -1 e.g. resource error.
The problem is that returning (char *) -1 will break all sorts of other
code, so while what we did is correct, the real failure case fix is slightly
broader.
There are 3 other places where _nl_find_msg is called:
(a) Recursively in _nl_find_msg.
Here we return -1 immediately if a recursive call to _nl_find_msg
returns -1. Resource errors are fatal at this point and if we
continue it just makes the matter worse by trying to allocate other
structure like conv_tab.
(b) From _nl_load_domain.
Here the error is also fatal, the domain is incomplete without
pluralization information and the failure in _nl_find_msg means
we won't be able to setup pluralization. We finalize the lock
we just initialized and exit via the normal error path.
(c) From DCIGETTEXT.
The error is not fatal here, it just means we have no translation.
We *might* be able to keep going without any problems so we return
via the normal no-translations path.
Patch follows against 2.18 upstream, but should equally apply to
rawhide, f19, and f18 which have similar code.
2013-05-03 Carlos O'Donell <carlos(a)redhat.com>
* intl/dcigettext.c (DCIGETTEXT): Skip translating if _nl_find_msg returns -1.
(_nl_find_msg): Return -1 if recursive call returned -1. If newmem is null
return -1.
* intl/loadmsgcat.c (_nl_load_domain): If _nl_find_msg returns -1 abort
loading the domain.
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index 110307b..f4aa215 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -638,6 +638,11 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
retval = _nl_find_msg (domain->successor[cnt], binding,
msgid1, 1, &retlen);
+ /* Resource problems are not fatal, instead we return no
+ translation. */
+ if (__builtin_expect (retval == (char *) -1, 0))
+ goto no_translation;
+
if (retval != NULL)
{
domain = domain->successor[cnt];
@@ -941,6 +946,11 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
nullentry =
_nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+ /* Resource problems are fatal. If we continue onwards we will
+ only attempt to calloc a new conv_tab and fail later. */
+ if (__builtin_expect (nullentry == (char *) -1, 0))
+ return (char *) -1;
+
if (nullentry != NULL)
{
const char *charsetstr;
@@ -1170,10 +1180,14 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp)
freemem_size = INITIAL_BLOCK_SIZE;
newmem = (transmem_block_t *) malloc (freemem_size);
# ifdef _LIBC
- /* Add the block to the list of blocks we have to free
- at some point. */
- newmem->next = transmem_list;
- transmem_list = newmem;
+ if (newmem != NULL)
+ {
+ /* Add the block to the list of blocks we have to free
+ at some point. */
+ newmem->next = transmem_list;
+ transmem_list = newmem;
+ }
+ /* Fall through and return -1. */
# endif
}
if (__builtin_expect (newmem == NULL, 0))
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index e4b7b38..ac90ed1 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -1237,7 +1237,7 @@ _nl_load_domain (domain_file, domainbinding)
default:
/* This is an invalid revision. */
invalid:
- /* This is an invalid .mo file. */
+ /* This is an invalid .mo file or we ran out of resources. */
free (domain->malloced);
#ifdef HAVE_MMAP
if (use_mmap)
@@ -1257,6 +1257,11 @@ _nl_load_domain (domain_file, domainbinding)
/* Get the header entry and look for a plural specification. */
nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+ if (__builtin_expect (nullentry == (char *) -1, 0))
+ {
+ __libc_rwlock_fini (domain->conversions_lock);
+ goto invalid;
+ }
EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
out:
---
Cheers,
Carlos.
10 years, 11 months
First post.
by Carlos O'Donell
This is the first post to the list.
Enjoy.
Cheers,
Carlos.
10 years, 11 months