This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug network/17630] New: endless loop in getaddr_r
- From: "yashavanth.hsn at gmail dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Thu, 20 Nov 2014 13:44:19 +0000
- Subject: [Bug network/17630] New: endless loop in getaddr_r
- Auto-submitted: auto-generated
https://sourceware.org/bugzilla/show_bug.cgi?id=17630
Bug ID: 17630
Summary: endless loop in getaddr_r
Product: glibc
Version: 2.11
Status: NEW
Severity: normal
Priority: P2
Component: network
Assignee: unassigned at sourceware dot org
Reporter: yashavanth.hsn at gmail dot com
Hallo,
DESCRIPTION: getanswer_r ends in infinite loop on certain inputs.
GLIBC_VERSION: 2.11.3
Note: I am novice into glibc and don't have complete understanding of glibc
with respect to dns resolution.
IN DETAIL:
When I execute iptables-restore on one of our Lab's system, iptables-restore
started consuming 100% cpu all the time. I did strace on iptables-restore I
found that most of the cpu is comsumed by NSS DNS resolver of libc as given
below.
67.50% iptables-restor libnss_dns-2.11.3.so [.] getanswer_r
15.12% iptables-restor libc-2.11.3.so [.] __strcasecmp
9.02% iptables-restor libc-2.11.3.so [.] __ctype_b_loc
7.02% iptables-restor libc-2.11.3.so [.] __i686.get_pc_thunk.bx
0.77% iptables-restor libnss_dns-2.11.3.so [.] 0x00000c00
0.18% iptables-restor [kernel.kallsyms] [k] read_hpet
To get more details, I attached iptables-restore to gdb with debugging symbols
loaded and found that glibc takes most of the CPU, since it ends in endless
loop. when,
1. have_answer is set
2. net_i is set to BYNAME
3. result->n_aliases is set to ns5.dsredirections.com ( i,e in the code ap is
set to ns5.dsredirections.com )
With this input, I found that the loop never exists and continue to process the
same input again and again.
Basically as per the code comment, the loop functionality is to :
/* Check each alias name for being of the forms:
4.3.2.1.in-addr.arpa = net 1.2.3.4
3.2.1.in-addr.arpa = net 0.1.2.3
2.1.in-addr.arpa = net 0.0.1.2
1.in-addr.arpa = net 0.0.0.1
*/
But then the question is :
1. Is this is a valid input or not to getanswer_r.
on the other hand, when the input is of bad form like ns5.dsredirections.com,
code has to detect and come out of loop.
FINDINGS and SOLUTION:
I found that the most recent Upstream code does not have this fixed as this
part of the code is stable since 2002.
** I tried to patch glibc as given below. ( Not sure if its correct and does
not break other scenarios )
avoid infinite loop for invalid entry.
getaddr_r gets into infinite loop for invalid entries
like ns5.dsredirections.com then it never detects and
breaks from infinite loop.
This patch detects the entries with non digit and
non hexadecimal digits and returns.
diff --git a/glibc/glibc-2.11.3-getaddr.diff b/glibc/glibc-2.11.3-getaddr.diff
new file mode 100644
index 0000000..664b033
--- /dev/null
+++ b/glibc/glibc-2.11.3-getaddr.diff
@@ -0,0 +1,42 @@
+Index: glibc-2.11.3/resolv/nss_dns/dns-network.c
+===================================================================
+--- glibc-2.11.3.orig/resolv/nss_dns/dns-network.c
++++ glibc-2.11.3/resolv/nss_dns/dns-network.c
+@@ -414,6 +414,7 @@ getanswer_r (const querybuf *answer, int
+ uint32_t val = 0; /* Accumulator for n_net value. */
+ unsigned int shift = 0; /* Which part we are parsing now. */
+ const char *p = *ap; /* Consuming the string. */
++ unsigned int invalid = 0;
+ do
+ {
+ /* Match the leading 0 or 0[xX] base indicator. */
+@@ -440,12 +441,23 @@ getanswer_r (const querybuf *answer, int
+ part = (part * base) + (*p - '0');
+ else if (base == 16 && isxdigit (*p))
+ part = (part << 4) + 10 + (tolower (*p) - 'a');
++
++ /* when neither digit nor hexadigit, then its a invalid
*/
++ if ( !isdigit(*p) && !isxdigit(*p) && *p != '.')
++ {
++ invalid = 1;
++ }
++
+ ++p;
+ } while (*p != '\0' && *p != '.');
+
++ if( invalid )
++ return NSS_STATUS_NOTFOUND;
++
+ if (*p != '.')
+ break; /* Bad form. Give up on this name. */
+
++
+ /* Install this as the next more significant byte. */
+ val |= part << shift;
+ shift += 8;
+@@ -470,4 +482,4 @@ getanswer_r (const querybuf *answer, int
+
+ __set_h_errno (TRY_AGAIN);
+ return NSS_STATUS_TRYAGAIN;
+-}
++}
After the patched glibc is installed, iptables-restore does not run infinitely
and everything is normal.
Could you please let me know, whether this will be fixed moving further.
I would like to extend my help with any information if needed.
Best,
Yash
--
You are receiving this mail because:
You are on the CC list for the bug.