[PATCH] resolv: Count records, and check hostname (CVE-2026-4437, CVE-2026-4438)

Florian Weimer fweimer@redhat.com
Fri Mar 20 20:39:01 GMT 2026


* Carlos O'Donell:

> On 3/20/26 4:11 PM, Florian Weimer wrote:
>> * Carlos O'Donell:
>> 
>>> 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.
>>>
>>> The processed hostname in getanswer_ptr should be correctly checked to
>>> avoid invalid characters from being allowed, including shell
>>> metacharacters. It is a security issue to fail to check the returned
>>> hostname for validity.
>>>
>>> These two issues are considered distinct CVEs, but are fixed in one
>>> commit to make the update process easier, given that they change the
>>> same file and function.
>>>
>>> Regression tests are added for invalid metacharacters and response
>>> section crossing.
>>>
>>> No regressions on x86_64-linux-gnu.
>>> ---
>>>   resolv/Makefile                 |   7 +
>>>   resolv/nss_dns/dns-host.c       |   4 +-
>>>   resolv/tst-resolv-dns-section.c | 161 ++++++++++++++++++++
>>>   resolv/tst-resolv-invalid-ptr.c | 258 ++++++++++++++++++++++++++++++++
>>>   4 files changed, 428 insertions(+), 2 deletions(-)
>>>   create mode 100644 resolv/tst-resolv-dns-section.c
>>>   create mode 100644 resolv/tst-resolv-invalid-ptr.c

>> I don't quite understand why this is a single commit for two bugs
>> that have very different impact, fixes, and even separate test cases.
>
> The justification is in the commit log? :-)
> ~~~
> These two issues are considered distinct CVEs, but are fixed in one
> commit to make the update process easier, given that they change the
> same file and function.
> ~~~

If that's the only justification, I don't think we should put both into
one patch.

Couple of review notes:

> +  if (strstr (qname, "in-addr.arpa") != NULL
> +      && sscanf (qname, "%u.%ms", &count, &tail) == 2)
> +    TEST_COMPARE_STRING (tail, "0.168.192.in-addr.arpa");
> +  else if (sscanf (qname, "%x.%ms", &count, &tail) == 3)
> +    {
> +    TEST_COMPARE_STRING (tail, "\
> +0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
> +    }

It seems that tail is never freed?

This also applies to the second test case.

> +  TEST_VERIFY (count <= 15);

> +  TEST_VERIFY (count < 16);

These checks should use array_length (test_items).

This also applies to the second test case.

> +  if (answer != NULL)
> +    {
> +      printf ("INFO: %s\n", support_format_hostent (answer));
> +      TEST_COMPARE_STRING (answer->h_name, "test.ptr.example.net");
> +    }

This is after the failure, and the information is already included in
the support_format_hostent output, so the TEST_COMPARE_STRING seems
quite redundant?  And printf could say "error: unexpected success: %s\n".
The last part also applies to the second test.

> +    /* Test for invalid UTF-8 characters (2-byte, 4-byte, 6-byte).  */
> +    { "Invalid use of UTF-8 (2-byte, U+00C0-U+00C2)",
> +      "ÁÂÃ.test.ptr.example", NO_RECOVERY, true },
> +    { "Invalid use of UTF-8 (4-byte, U+0750-U+0752)",
> +      "ݐݑݒ.test.ptr.example", NO_RECOVERY, true },
> +     { "Invalid use of UTF-8 (6-byte, U+0904-U+0906)",
> +      "ऄअआ.test.ptr.example", NO_RECOVERY, true },

The use of UTF-8 might be tricky to backport for some environments.

> +      TEST_VERIFY (answer != NULL);
> +      /* And it must match what we provided.  */
> +      if (answer != NULL)
> +        TEST_COMPARE_STRING (answer->h_name, test_items[count].answer);

TEST_COMPARE_STRING already handles NULL, so the extra checks aren't
necessary.

Thanks,
Florian



More information about the Libc-alpha mailing list