[PATCH] resolv: Add test for gethostbyname_r unaligned buffer [BZ #18287]

Florian Weimer fweimer@redhat.com
Thu Jun 18 13:07:25 GMT 2026


* Sergey Kolosov:

>  resolv/tst-resolv-gethostbyname_r-unaligned.c | 158 ++++++++++++++++++

The test file contains a couple of lines with trailing whitespace.
Please fix.

>  2 files changed, 161 insertions(+)
> diff --git a/resolv/tst-resolv-gethostbyname_r-unaligned.c b/resolv/tst-resolv-gethostbyname_r-unaligned.c
> new file mode 100644
> index 0000000000..7298c6f8e6
> --- /dev/null
> +++ b/resolv/tst-resolv-gethostbyname_r-unaligned.c
> @@ -0,0 +1,158 @@

> +static int
> +query_host (const char *host_name, size_t size, int align)

size_t align?

> +{
> +  struct hostent ret;
> +  struct hostent *result;
> +  int err;
> +
> +  /* Allocate memory for buffer, align and 64 bytes.  */

“alignment and a 64-byte checking area”?

> +  size_t total_alloc = size + align + 64;
> +  unsigned char *raw_buf = malloc (total_alloc);
> +  TEST_VERIFY_EXIT (raw_buf != NULL);
> +
> +  /* Fill in buffer with 0xAA to detect buffer overflow.  */
> +  memset (raw_buf, 0, size + align);
> +  memset (raw_buf + size + align, 0xAA, 64);
> +  
> +  char *ptr = (char *) raw_buf + align;
> +
> +  int res = gethostbyname_r (host_name, &ret, ptr, size, &result, &err);
> +
> +  /* Verify that the overflow guard region remains unchanged.  */
> +  int overflow_detected = 0;
> +  for (int i = 0; i < 64; i++)
> +    {
> +      if (raw_buf[size + align + i] != 0xAA)
> +        {
> +          overflow_detected = 1;
> +          break;
> +        }
> +    }
> +
> +  free (raw_buf);
> +
> +  if (overflow_detected)
> +    {
> +      printf ("Buffer overflow was detected! (align=%d, size=%zu)\n",
> +              align, size);
> +      /* Return 99 to indicate that a buffer overflow was detected.  */
> +      return 99;
> +    }

I think it's okay to use FAIL_EXIT1 and avoid the 99 special return
code.

Then you can switch the return to bool.  Please also add a function
comment for query_host that explains the parameters and the return
value.

> +  if (res == 0 && result != NULL)
> +    return 0; /* Buffer is enough.  */

Maybe also use check_hostent to check that the response is as expected?
(This may require changeing response so that it always provides the
same response.)

> +  else if (res == ERANGE || err == NETDB_INTERNAL)
> +    return 1; /* Buffer is too small.  */

I think the || should be &&.


> +  /* Trigger the vulnerability.
> +     Test all misalignments (1-7 bytes). A patched glibc safely
> +     returns 0 (success) or 1 (ERANGE) depending on padding.
> +     A vulnerable glibc will fail to account for alignment padding,
> +     overflow the buffer, corrupt the 0xAA canary, and return 99.  */

This comment needs updating once you eliminate the special 99 return
value.

> +  for (int align = 1; align < 8; align++)
> +    {
> +      int qres = query_host (host_name, upper_bound, align);
> +      
> +      if (qres == 99)
> +        FAIL_EXIT1 ("Buffer overflow detected at align %d\n", align);
> +      
> +      /* Return value other than 99 means no overflow occurred.  */
> +      TEST_VERIFY (qres == 0 || qres == 1);

Maybe add a comment that it is expected that for certain alignments, the
required buffer size increases.

Thanks,
Florian



More information about the Libc-alpha mailing list