[PATCH v2 1/2] resolv: Count records correctly (CVE-2026-4437)
Collin Funk
collin.funk1@gmail.com
Fri Mar 20 23:26:20 GMT 2026
Carlos O'Donell <carlos@redhat.com> writes:
> The answer section boundary was previously ignored, and the code in
> getanswer_ptr would iterate past the last resource record, but not
> beyond the end of the returned data. This could lead to subsequent data
> being interpreted as answer records, thus violating the DNS
> specification. Such resource records could be maliciously crafted and
> hidden from other tooling, but processed by the glibc stub resolver and
> acted upon by the application. While we trust the data returned by the
> configured recursive resolvers, we should not trust its format and
> should validate it as required. It is a security issue to incorrectly
> process the DNS protocol.
>
> A regression test is added for response section crossing.
>
> No regressions on x86_64-linux-gnu.
> ---
> v1 -> v2
> - Split out changes for CVE-2026-4437
> - Incorporate Florian's suggestions.
> - Remove not-needed xmemstream.h included.
> - Fix IPv6 test to properly scan count via sscanf.
> - A/B tested changes again to review error messages on failure.
>
> resolv/Makefile | 4 +
> resolv/nss_dns/dns-host.c | 2 +-
> resolv/tst-resolv-dns-section.c | 162 ++++++++++++++++++++++++++++++++
> 3 files changed, 167 insertions(+), 1 deletion(-)
> create mode 100644 resolv/tst-resolv-dns-section.c
>
> diff --git a/resolv/Makefile b/resolv/Makefile
> index 34916a90cc..95bad5df27 100644
> --- a/resolv/Makefile
> +++ b/resolv/Makefile
> @@ -114,6 +114,7 @@ tests += \
> tst-resolv-basic \
> tst-resolv-binary \
> tst-resolv-byaddr \
> + tst-resolv-dns-section \
> tst-resolv-edns \
> tst-resolv-invalid-cname \
> tst-resolv-network \
> @@ -125,6 +126,7 @@ tests += \
> tst-resolv-semi-failure \
> tst-resolv-short-response \
> tst-resolv-trailing \
> + # tests
>
> # This test calls __res_context_send directly, which is not exported
> # from libresolv.
> @@ -299,6 +301,8 @@ $(objpfx)tst-resolv-aliases: $(objpfx)libresolv.so $(shared-thread-library)
> $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
> $(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
> $(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
> +$(objpfx)tst-resolv-dns-section: $(objpfx)libresolv.so \
> + $(shared-thread-library)
> $(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
> $(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
> $(objpfx)tst-resolv-res_init: $(objpfx)libresolv.so
> diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
> index 6a60c87532..893137027e 100644
> --- a/resolv/nss_dns/dns-host.c
> +++ b/resolv/nss_dns/dns-host.c
> @@ -820,7 +820,7 @@ getanswer_ptr (unsigned char *packet, size_t packetlen,
> /* expected_name may be updated to point into this buffer. */
> unsigned char name_buffer[NS_MAXCDNAME];
>
> - while (ancount > 0)
> + for (; ancount > 0; --ancount)
> {
This change looks good to me. The rest of the code in that file checks
the answer section boundary in the same way as this change. Also, I
confirmed your test catches the bug.
Reviewed-by: Collin Funk <collin.funk1@gmail.com>
Thanks,
Collin
More information about the Libc-alpha
mailing list