|
Message-ID: <CAFBikZ6FV0jkKwLA9rRz3WcsMpeZ5R6aSjYA5eOe_9vGDVThaw@mail.gmail.com>
Date: Wed, 19 Oct 2022 00:02:36 +0800
From: Tom Shen <sjiagc.dev@...il.com>
To: musl@...ts.openwall.com
Subject: gethostbyname2_r returns invalid IPv6 address if DNS server replies
IPv4 address
Hi Musl team,
Recently we encountered an issue in requesting name resolution in Alpine
Linux with Musl.
Environment:
* Alpine Linux 3.14.2
* IPv6 module disabled
* musl-libc 1.2.2
* CoreDNS with "rewrite stop type AAAA A" configured
Reproduce steps:
1. getent hosts <any-name-only-has-ipv4-record>
2. Check output
Expected: Get correct IPv4 address, e.g. 10.96.36.74
Actual: Return an invalid IPv6 address, e.g. a60:244a::, which is the
actual IPv4 32-bit address followed by zeros.
Debugging:
1. Alpine Linux's getent (
https://github.com/alpinelinux/aports/blob/3.14-stable/main/musl/getent.c)
tries gethostbyname2 with AF_INET6 first, if no result, then calls with
AF_INET.
2. With requested family AF_INET6, gethostbyname2_r -> __lookup_name
-> name_from_dns_search sends a DNS request with RR_AAAA to CoreDNS.
3. In CoreDNS, we configured "rewrite stop type AAAA A", which results in
the RR_AAAA request type being rewritten to RR_A. So the response from
CoreDNS is: AF_INET (2) and 32-bit IP 10.96.36.74 (0x0a60244a below).
> (gdb) p addrs
> $55 = {{family = 2, scopeid = 0, addr = "\n`$J", '\000' <repeats 11
> times>, sortkey = 0}
> (gdb) x/4xb addrs[0]->addr
> 0x7fffffffe0d8: 0x0a 0x60 0x24 0x4a
>
4. In gethostbyname2_r, the result address family is assigned to the
request's family, regardless of the family in the response.
> h->h_addrtype = af;
> h->h_length = af==AF_INET6 ? 16 : 4;
>
This results in the IPv4 address replied from CoreDNS is wrongly copied to
the result as IPv6 address which is a60:244a:: .
5. getent gets an IPv4 address, so it won't try AF_INET, rather directly
return the invalid IPv6 address a60:244a:: .
Suggested fix:
In gethostbyname2_r when adding answered addresses into the result, we need
to filter out the addresses with mismatching address family.
> for (i=0; i<cnt; i++) {
> // if (addrs[i].family != h->h_addrtype) continue; // need to fix the
> index of h->h_addr_list too
> h->h_addr_list[i] = (void *)buf;
> buf += h->h_length;
> memcpy(h->h_addr_list[i], addrs[i].addr, h->h_length);
> }
>
Could you review this issue? Thanks in advance!
Best regards!
Tom Shen
Content of type "text/html" skipped
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.