[PATCHv3] malloc: Make sure tcache_key is odd enough

Cupertino Miranda cupertino.miranda@oracle.com
Mon Aug 4 09:51:42 GMT 2025


Hi Samuel, Wilco

For whatever is worth, patch looks good to me.

In order to avoid having tcache_key repeated through memory, why don't 
we mangle it as well with, maybe not exactly as in PROTECT_PTR, however 
using the location of chunk. A XOR perhaps ?

I don't think it would have such a huge performance impact on the 
overhaul execution time.

What do you think?

Cheers,
Cupertino


On 04-08-2025 10:41, Samuel Thibault wrote:
> 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: c968fe50628db74b52124d863cd828225a1d305c ("malloc: Use tailcalls in __libc_free")
> ---
>   malloc/malloc.c | 16 ++++++++++++++++
>   1 file changed, 16 insertions(+)
> 
> Change from v2: Fix line width to < 80
> 
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 9d646abae9..221a21e946 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -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>
>   
> @@ -3097,6 +3100,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



More information about the Libc-alpha mailing list