aboutsummaryrefslogtreecommitdiff
path: root/malloc/malloc.c
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2025-07-30 01:55:22 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2025-08-10 09:44:08 +0200
commit2536c4f8584082a1ac4c5e0a2a6222e290d43983 (patch)
tree9d51e4b4ede025c58d5d452f49a1c4bb7fb76536 /malloc/malloc.c
parenta6eb8285d9bfb7ec0875b85ca356e833ff964d4f (diff)
downloadglibc-master.zip
glibc-master.tar.gz
glibc-master.tar.bz2
malloc: Make sure tcache_key is odd enoughHEADmaster
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")
Diffstat (limited to 'malloc/malloc.c')
-rw-r--r--malloc/malloc.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 3a8aaeb..c135916 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>
@@ -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