Bug 14498

Summary: default /var/db/services.db triggers infinite CPU loop with getaddrinfo()
Product: glibc Reporter: Mike Frysinger <vapier>
Component: networkAssignee: Alexandre Oliva <aoliva>
Status: RESOLVED FIXED    
Severity: normal CC: aoliva, cloos, fweimer, toolchain
Priority: P2 Flags: fweimer: security-
Version: unspecified   
Target Milestone: ---   
Host: x86_64-linux-gnu Target:
Build: Last reconfirmed:
Attachments: generated services.db
/etc/services
two patches in one, both fixing the problem

Description Mike Frysinger 2012-08-20 03:26:40 UTC
using the default /var/db/Makefile provided by glibc:
cd /var/db
rm -f *.db
make

then running a simple getaddrinfo() request:
wget https://432020.bugs.gentoo.org/attachment.cgi?id=321736 -O test.c
gcc test.c
./a.out
<hang>

seems like we trigger an infinite cpu loop somewhere in the look up logic

(all details and example code provided by Maxim Kammerer)

reproduced with glibc-2.15 and 2.16
Comment 1 Andreas Schwab 2013-01-15 11:04:05 UTC
I cannot reproduce that with 2.17.  Does it still happen?
Comment 2 Mike Frysinger 2013-01-15 17:50:41 UTC
it is still hanging for me w/2.17.  i am not running nscd.

the Gentoo patchset is small, but lemme double check it fails on vanilla 2.17.
Comment 3 Mike Frysinger 2013-01-15 18:36:00 UTC
just tried latest master (357679d2fc567e8d6c030cf0f0fd54f6c31e23a3) and it still fails with the test case

maybe the input /etc/services matters ?  here's my /etc/services and services.db.
Comment 4 Mike Frysinger 2013-01-15 18:36:53 UTC
Created attachment 6819 [details]
generated services.db
Comment 5 Mike Frysinger 2013-01-15 18:37:53 UTC
Created attachment 6820 [details]
/etc/services
Comment 6 Mike Frysinger 2013-01-15 18:41:54 UTC
hmm, if i chop my /etc/services at line ~250 (first line to delete: cisco-fna), then i can build a services.db and the test case does not hang ...
Comment 7 Alexandre Oliva 2014-10-31 06:02:47 UTC
Created attachment 7872 [details]
two patches in one, both fixing the problem

We use some code from nss_files in nss_db, and nss_files' code used “continue” to skip a non-matching proto, but in nss_db this bypassed the code to advance to the next entry.  Both changes individually fix the problem; I'm undecided as to which one to go with, or maybe even go with both.  Thoughts?
Comment 8 cvs-commit@gcc.gnu.org 2014-11-21 05:42:43 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  b59d114bd1e0571fba85b3cbcc61d4f4b42f5d1b (commit)
       via  f3d945d5f2b9d7d44032c461af588c6d54f5664b (commit)
       via  4969890247d7d6a548f17641ed5a18f4b713d211 (commit)
      from  81959214868c9ac9e425fbf0fa3fd9135e207f7e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=b59d114bd1e0571fba85b3cbcc61d4f4b42f5d1b

commit b59d114bd1e0571fba85b3cbcc61d4f4b42f5d1b
Author: Alexandre Oliva <aoliva@redhat.com>
Date:   Sat Sep 27 07:23:39 2014 -0300

    BZ#16469: resolv: skip leading dot in domain to search
    
    This should only happen if the domain to search is the root,
    represented as "." rather than by an empty string.  Skipping it here
    prevents libc_res_nquerydomain from duplicating the trailing dot,
    which would cause the domain name compression to fail.
    
    for  ChangeLog
    
    	[BZ #16469]
    	* resolv/res_query.c (__libc_res_nsearch): Skip leading dot in
    	search domain names.

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f3d945d5f2b9d7d44032c461af588c6d54f5664b

commit f3d945d5f2b9d7d44032c461af588c6d54f5664b
Author: Alexandre Oliva <aoliva@redhat.com>
Date:   Sun Nov 9 13:51:09 2014 -0200

    BZ#16469: don't drop trailing dot in res_nquerydomain(..., name, NULL, ...)
    
    If we drop it here, we will fail to detect a duplicate trailing dot
    later on.  Retaining, OTOH, has no ill effects whatsoever, and it even
    saves us the trouble of copying the domain name minus the trailing
    dot, like we used to do.
    
    for ChangeLog
    
    	[BZ #16469]
    	* NEWS: Update.
    	* resolv/res_query.c (__libc_res_nquerydomain): Retain
    	trailing dot.
    	* posix/tst-getaddrinfo5.c: New.
    	* posix/Makefile (tests): Add it.

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=4969890247d7d6a548f17641ed5a18f4b713d211

commit 4969890247d7d6a548f17641ed5a18f4b713d211
Author: Alexandre Oliva <aoliva@redhat.com>
Date:   Fri Nov 21 03:29:56 2014 -0200

    BZ#14498: fix infinite loop in nss_db_getservbyname
    
    nss_db uses nss_files code for services, but a continue on protocol
    mismatch that doesn't affect nss_files skipped the code that advanced
    to the next db entry.  Any one of these changes would suffice to fix
    it, but fixing both makes them both safer to reuse elsewhere.
    
    for  ChangeLog
    
    	[BZ #14498]
    	* NEWS: Fixed.
    	* nss/nss_db/db-XXX.c (_nss_db_get##name##_r): Update hidx
    	after parsing line but before break_if_match.
    	* nss/nss_files/files-service (DB_LOOKUP): Don't "continue;"
    	if there is a protocol mismatch.

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                     |   24 ++++++++++++++
 NEWS                          |    8 ++--
 nss/nss_db/db-XXX.c           |    9 +++--
 nss/nss_files/files-service.c |    7 +++-
 posix/Makefile                |    2 +-
 posix/tst-getaddrinfo5.c      |   69 +++++++++++++++++++++++++++++++++++++++++
 resolv/res_query.c            |   30 +++++++++--------
 7 files changed, 125 insertions(+), 24 deletions(-)
 create mode 100644 posix/tst-getaddrinfo5.c
Comment 9 Alexandre Oliva 2014-11-21 06:27:55 UTC
Fixed