Bug 25222 - getaddrinfo("localhost") returns 2x 127.0.0.1
Summary: getaddrinfo("localhost") returns 2x 127.0.0.1
Status: UNCONFIRMED
Alias: None
Product: glibc
Classification: Unclassified
Component: nss (show other bugs)
Version: 2.31
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-11-23 17:05 UTC by Tim Rühsen
Modified: 2020-02-19 15:18 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
[getaddrinfo] ignore ::1 in /etc/hosts if asked for AF_INET localhost (667 bytes, patch)
2019-11-23 17:05 UTC, Tim Rühsen
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tim Rühsen 2019-11-23 17:05:39 UTC
Created attachment 12090 [details]
[getaddrinfo] ignore ::1 in /etc/hosts if asked for AF_INET localhost

Given that /etc/hosts contains ::1 and 127.0.0.1 for localhost, getaddrinfo() returns two identical entries 127.0.0.1, even if the hints are set to AF_INET.

Example /etc/hosts
127.0.0.1  localhost localhost4
::1        localhost localhost6

The code for this was introduced in 2007 by commit 11bf311edc7.

There is an explicit code branch executed if AF_INET has been requested and a IPv6 address has been found (makes sense with V4MAPPED). But if IPv4 mapping is not used and the IP is ::1, the code simply adds an entry with 127.0.0.1. This creates the second 127.0.0.1 entry mentioned above.

Removing the code (attached patch), the glibc test suite results do not change here.

C example code
###
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>

int main(void)
{
        struct addrinfo hints = {
                .ai_family = AF_INET,
                .ai_socktype = SOCK_STREAM,
                .ai_flags = AI_ADDRCONFIG
        };
        const char *host = "localhost";
        struct addrinfo *addrinfo;
        int rc;

        if ((rc = getaddrinfo(host, NULL, &hints, &addrinfo)) == 0) {
                for (struct addrinfo *ai = addrinfo; ai; ai = ai->ai_next) {
                        char adr[NI_MAXHOST];
                        int rc;

                        if ((rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, adr, sizeof(adr), NULL, 0, NI_NUMERICHOST)) == 0)
                                printf("%s\n", adr);
                        else
                                printf("??? (%s)\n", gai_strerror(rc));
                }
        } else
                printf("rc = %d %s, errno %d\n", rc, gai_strerror(rc), errno);

        return 0;
}
###