[PATCH v2 1/2] resolv: Count records correctly (CVE-2026-4437)

Carlos O'Donell carlos@redhat.com
Mon Mar 23 20:58:09 GMT 2026


On 3/20/26 7:26 PM, Collin Funk wrote:
> 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. Pushed. I'll update the advisory with the fixed commit.

-- 
Cheers,
Carlos.



More information about the Libc-alpha mailing list