[v5,5/7] malloc: mangle tcache entries pointers

Message ID 20250321120102.54012-6-cupertino.miranda@oracle.com (mailing list archive)
State Under Review
Delegated to: Wilco Dijkstra
Headers
Series tcache: malloc improvements |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 fail Test failed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed

Commit Message

Cupertino Miranda March 21, 2025, 12:01 p.m. UTC
  tcache entries are store in mangled linked lists of chunks.
However the initial pointer stored in tcache->entries[index] is stored
unmangled.
Due to this difference, tcache_get_n contains 2 extra conditions to
disambiguate between the original pointer from tcache entries, or the
next pointer within the content of the chunk.

This patch slightly improves tcache_get_n by removing the condition
related to refering to the first pointer by also mangling the pointers
stored in tcache->entries.
The mangling of the entries should also happen on tcache_init as NULL
pointers are also mangled.
---
 malloc/malloc.c | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)
  

Patch

diff --git a/malloc/malloc.c b/malloc/malloc.c
index ea2da0c9fc..c942e3f8d1 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3164,8 +3164,8 @@  tcache_put (mchunkptr chunk, size_t tc_idx)
      detect a double free.  */
   e->key = tcache_key;
 
-  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
-  tcache->entries[tc_idx] = e;
+  e->next = PROTECT_PTR (&e->next, REVEAL_PTR (tcache->entries[tc_idx]));
+  tcache->entries[tc_idx] = PROTECT_PTR (&(tcache->entries[tc_idx]), e);
   ++(tcache->counts[tc_idx]);
 }
 
@@ -3175,19 +3175,12 @@  tcache_put (mchunkptr chunk, size_t tc_idx)
 static __always_inline void *
 tcache_get_n (size_t tc_idx, tcache_entry **ep)
 {
-  tcache_entry *e;
-  if (ep == &(tcache->entries[tc_idx]))
-    e = *ep;
-  else
-    e = REVEAL_PTR (*ep);
+  tcache_entry *e = REVEAL_PTR (*ep);
 
   if (__glibc_unlikely (!aligned_OK (e)))
     malloc_printerr ("malloc(): unaligned tcache chunk detected");
 
-  if (ep == &(tcache->entries[tc_idx]))
-      *ep = REVEAL_PTR (e->next);
-  else
-    *ep = PROTECT_PTR (ep, REVEAL_PTR (e->next));
+  *ep = PROTECT_PTR (ep, REVEAL_PTR (e->next));
 
   --(tcache->counts[tc_idx]);
   e->key = 0;
@@ -3228,7 +3221,7 @@  tcache_double_free_verify (tcache_entry *e, size_t tc_idx)
   tcache_entry *tmp;
   size_t cnt = 0;
   LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
-  for (tmp = tcache->entries[tc_idx];
+  for (tmp = REVEAL_PTR (tcache->entries[tc_idx]);
        tmp;
        tmp = REVEAL_PTR (tmp->next), ++cnt)
     {
@@ -3290,13 +3283,13 @@  tcache_thread_shutdown (void)
      heap for coalescing.  */
   for (i = 0; i < TCACHE_MAX_BINS; ++i)
     {
-      while (tcache_tmp->entries[i])
+      while (REVEAL_PTR (tcache_tmp->entries[i]))
 	{
-	  tcache_entry *e = tcache_tmp->entries[i];
+	  tcache_entry *e = REVEAL_PTR (tcache_tmp->entries[i]);
 	  if (__glibc_unlikely (!aligned_OK (e)))
 	    malloc_printerr ("tcache_thread_shutdown(): "
 			     "unaligned tcache chunk detected");
-	  tcache_tmp->entries[i] = REVEAL_PTR (e->next);
+	  tcache_tmp->entries[i] = PROTECT_PTR (&(tcache_tmp->entries[i]), REVEAL_PTR (e->next));
 	  __libc_free (e);
 	}
     }
@@ -3337,6 +3330,8 @@  tcache_init(void)
       memset (tcache, 0, sizeof (tcache_perthread_struct));
     }
 
+  for (int i = 0; i < mp_.tcache_bins; i++)
+    tcache->entries[i] = PROTECT_PTR (&(tcache->entries[i]), NULL);
 }
 
 # define MAYBE_INIT_TCACHE() \
@@ -3699,7 +3694,7 @@  _mid_memalign (size_t alignment, size_t bytes, void *address)
       {
 	/* The tcache itself isn't encoded, but the chain is.  */
 	tcache_entry **tep = & tcache->entries[tc_idx];
-	tcache_entry *te = *tep;
+	tcache_entry *te = REVEAL_PTR (*tep);
 	while (te != NULL && !PTR_IS_ALIGNED (te, alignment))
 	  {
 	    tep = & (te->next);