[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