malloc: Make sure tcache_key is odd enough

We want tcache_key not to be a commonly-occurring value in memory, so ensure
a minimum amount of one and zero bits.

And we need it non-zero, otherwise even if tcache_double_free_verify sets
e->key to 0 before calling __libc_free, it gets called again by __libc_free,
thus looping indefinitely.

Fixes: c968fe5062 ("malloc: Use tailcalls in __libc_free")
This commit is contained in:
Samuel Thibault 2025-07-30 01:55:22 +02:00
parent a6eb8285d9
commit 2536c4f858
1 changed files with 16 additions and 0 deletions

View File

@ -230,6 +230,9 @@
/* For uintptr_t. */
#include <stdint.h>
/* For stdc_count_ones. */
#include <stdbit.h>
/* For va_arg, va_start, va_end. */
#include <stdarg.h>
@ -3095,6 +3098,19 @@ tcache_key_initialize (void)
if (__getrandom_nocancel_nostatus_direct (&tcache_key, sizeof(tcache_key),
GRND_NONBLOCK)
!= sizeof (tcache_key))
tcache_key = 0;
/* We need tcache_key to be non-zero (otherwise tcache_double_free_verify's
clearing of e->key would go unnoticed and it would loop getting called
through __libc_free), and we want tcache_key not to be a
commonly-occurring value in memory, so ensure a minimum amount of one and
zero bits. */
int minimum_bits = __WORDSIZE / 4;
int maximum_bits = __WORDSIZE - minimum_bits;
while (labs (tcache_key) <= 0x1000000
|| stdc_count_ones (tcache_key) < minimum_bits
|| stdc_count_ones (tcache_key) > maximum_bits)
{
tcache_key = random_bits ();
#if __WORDSIZE == 64