[PATCH 2/3] malloc: Remove code conditional on USE_MTAG

Yury Khrustalev yury.khrustalev@arm.com
Fri May 8 13:22:10 GMT 2026


Further malloc refactoring related to memory tagging.

Remove code that was only compiled when macro USE_MTAG was defined
except for the AArch64-specific assembly MTE code that is going to
be compiled unconditionally from now on.

As a result, we change 'mtag_mmap_flags' to 'extra_mmap_prot' that
is now always defined. Change of the name due to this being used
as part of PROT options in mmap syscalls rather than part of flags.

Remove 'mtag_enabled' that would become compile-time false. Also
remove any code that would never be compiled when 'mtag_enabled'
is false.
---
 malloc/arena.c                                | 18 +----
 malloc/malloc-check.c                         | 10 ---
 malloc/malloc.c                               | 73 +------------------
 sysdeps/aarch64/__mtag_tag_region.S           |  3 -
 sysdeps/aarch64/__mtag_tag_zero_region.S      |  3 -
 sysdeps/aarch64/cpu-features.h                |  3 +-
 sysdeps/aarch64/libc-mtag.h                   |  5 +-
 .../unix/sysv/linux/aarch64/cpu-features.c    | 28 -------
 8 files changed, 8 insertions(+), 135 deletions(-)

diff --git a/malloc/arena.c b/malloc/arena.c
index ddde32c712..023cb3ba06 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -252,20 +252,6 @@ __ptmalloc_init (void)
   tcache_key_initialize ();
 #endif
 
-#ifdef USE_MTAG
-  if ((TUNABLE_GET_FULL (glibc, mem, tagging, int32_t, NULL) & 1) != 0)
-    {
-      /* If the tunable says that we should be using tagged memory
-	 and that morecore does not support tagged regions, then
-	 disable it.  */
-      if (__MTAG_SBRK_UNTAGGED)
-	__always_fail_morecore = true;
-
-      mtag_enabled = true;
-      mtag_mmap_flags = __MTAG_MMAP_FLAGS;
-    }
-#endif
-
 #if defined SHARED && IS_IN (libc)
   /* In case this libc copy is in a non-default namespace, never use
      brk.  Likewise if dlopened from statically linked program.  The
@@ -417,7 +403,7 @@ alloc_new_heap  (size_t size, size_t top_pad, size_t pagesize,
             }
         }
     }
-  if (__mprotect (p2, size, mtag_mmap_flags | PROT_READ | PROT_WRITE) != 0)
+  if (__mprotect (p2, size, extra_mmap_prot | PROT_READ | PROT_WRITE) != 0)
     {
       __munmap (p2, max_size);
       return NULL;
@@ -471,7 +457,7 @@ grow_heap (heap_info *h, long diff)
     {
       if (__mprotect ((char *) h + h->mprotect_size,
                       (unsigned long) new_size - h->mprotect_size,
-                      mtag_mmap_flags | PROT_READ | PROT_WRITE) != 0)
+                      extra_mmap_prot | PROT_READ | PROT_WRITE) != 0)
         return -2;
 
       h->mprotect_size = new_size;
diff --git a/malloc/malloc-check.c b/malloc/malloc-check.c
index 49b623df12..ae5025d69a 100644
--- a/malloc/malloc-check.c
+++ b/malloc/malloc-check.c
@@ -217,11 +217,6 @@ free_check (void *mem)
 
   int err = errno;
 
-  /* Quickly check that the freed pointer matches the tag for the memory.
-     This gives a useful double-free detection.  */
-  if (__glibc_unlikely (mtag_enabled))
-    *(volatile char *)mem;
-
   __libc_lock_lock (main_arena.mutex);
   p = mem2chunk_check (mem, NULL);
   if (!p)
@@ -263,11 +258,6 @@ realloc_check (void *oldmem, size_t bytes)
       return NULL;
     }
 
-  /* Quickly check that the freed pointer matches the tag for the memory.
-     This gives a useful double-free detection.  */
-  if (__glibc_unlikely (mtag_enabled))
-    *(volatile char *)oldmem;
-
   __libc_lock_lock (main_arena.mutex);
   const mchunkptr oldp = mem2chunk_check (oldmem, &magic_p);
   __libc_lock_unlock (main_arena.mutex);
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 57b58382b1..d273c28501 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -405,27 +405,17 @@ verify (PTRDIFF_MAX <= SIZE_MAX / 2);
    tagging is not enabled, it simply returns the original pointer.
 */
 
-#ifdef USE_MTAG
-static bool mtag_enabled = false;
-static int mtag_mmap_flags = 0;
-#else
-# define mtag_enabled false
-# define mtag_mmap_flags 0
-#endif
+static int extra_mmap_prot = 0;
 
 static __always_inline void *
 tag_region (void *ptr, size_t size)
 {
-  if (__glibc_unlikely (mtag_enabled))
-    return __libc_mtag_tag_region (ptr, size);
   return ptr;
 }
 
 static __always_inline void *
 tag_new_zero_region (void *ptr, size_t size)
 {
-  if (__glibc_unlikely (mtag_enabled))
-    return __libc_mtag_tag_zero_region (__libc_mtag_new_tag (ptr), size);
   return memset (ptr, 0, size);
 }
 
@@ -436,8 +426,6 @@ tag_new_usable (void *ptr);
 static __always_inline void *
 tag_at (void *ptr)
 {
-  if (__glibc_unlikely (mtag_enabled))
-    return __libc_mtag_address_get_tag (ptr);
   return ptr;
 }
 
@@ -1259,23 +1247,6 @@ checked_request2size (size_t req) __nonnull (1)
 {
   if (__glibc_unlikely (req > PTRDIFF_MAX))
     return SIZE_MAX;
-
-  /* When using tagged memory, we cannot share the end of the user
-     block with the header for the next chunk, so ensure that we
-     allocate blocks that are rounded up to the granule size.  Take
-     care not to overflow from close to MAX_SIZE_T to a small
-     number.  Ideally, this would be part of request2size(), but that
-     must be a macro that produces a compile time constant if passed
-     a constant literal.  */
-  if (__glibc_unlikely (mtag_enabled))
-    {
-      /* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551.  */
-      asm ("");
-
-      req = (req + (__MTAG_GRANULE_SIZE - 1)) &
-	    ~(size_t)(__MTAG_GRANULE_SIZE - 1);
-    }
-
   return request2size (req);
 }
 
@@ -1378,25 +1349,11 @@ checked_request2size (size_t req) __nonnull (1)
 
 /* This is the size of the real usable data in the chunk.  Not valid for
    dumped heap chunks.  */
-#define memsize(p)                                                    \
-  (__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
-    chunksize (p) - CHUNK_HDR_SZ :                                    \
-    chunksize (p) - CHUNK_HDR_SZ + SIZE_SZ)
-
-/* If memory tagging is enabled the layout changes to accommodate the granule
-   size, this is wasteful for small allocations so not done by default.
-   Both the chunk header and user data has to be granule aligned.  */
-_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
-		"memory tagging is not supported with large granule.");
+#define memsize(p) (chunksize (p) - CHUNK_HDR_SZ + SIZE_SZ)
 
 static __always_inline void *
 tag_new_usable (void *ptr)
 {
-  if (__glibc_unlikely (mtag_enabled) && ptr)
-    {
-      mchunkptr cp = mem2chunk(ptr);
-      ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
-    }
   return ptr;
 }
 
@@ -2233,7 +2190,7 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags)
   size_t size = ALIGN_UP (nb + padding + CHUNK_HDR_SZ, pagesize);
 
   char *mm = (char *) MMAP (NULL, size,
-			    mtag_mmap_flags | PROT_READ | PROT_WRITE,
+			    extra_mmap_prot | PROT_READ | PROT_WRITE,
 			    extra_flags);
   if (mm == MAP_FAILED)
     return mm;
@@ -2274,7 +2231,7 @@ sysmalloc_mmap_fallback (size_t *s, size_t size, size_t minsize,
     size = minsize;
 
   char *mbrk = (char *) (MMAP (NULL, size,
-			       mtag_mmap_flags | PROT_READ | PROT_WRITE,
+			       extra_mmap_prot | PROT_READ | PROT_WRITE,
 			       extra_flags));
   if (mbrk == MAP_FAILED)
     return MAP_FAILED;
@@ -3301,11 +3258,6 @@ __libc_free (void *mem)
   if (mem == NULL)                              /* free(0) has no effect */
     return;
 
-  /* Quickly check that the freed pointer matches the tag for the memory.
-     This gives a useful double-free detection.  */
-  if (__glibc_unlikely (mtag_enabled))
-    *(volatile char *)mem;
-
   p = mem2chunk (mem);
 
   /* Mark the chunk as belonging to the library again.  */
@@ -3373,11 +3325,6 @@ __libc_realloc (void *oldmem, size_t bytes)
     }
 #endif
 
-  /* Perform a quick check to ensure that the pointer's tag matches the
-     memory's tag.  */
-  if (__glibc_unlikely (mtag_enabled))
-    *(volatile char*) oldmem;
-
   /* chunk corresponding to oldmem */
   const mchunkptr oldp = mem2chunk (oldmem);
 
@@ -3673,12 +3620,6 @@ __libc_calloc2 (size_t sz)
 
   p = mem2chunk (mem);
 
-  /* If we are using memory tagging, then we need to set the tags
-     regardless of MORECORE_CLEARS, so we zero the whole block while
-     doing so.  */
-  if (__glibc_unlikely (mtag_enabled))
-    return tag_new_zero_region (mem, memsize (p));
-
   csz = chunksize (p);
 
   /* Two optional cases in which clearing not necessary */
@@ -3725,9 +3666,6 @@ __libc_calloc (size_t n, size_t elem_size)
 	  if (tcache->entries[tc_idx] != NULL)
 	    {
 	      void *mem = tcache_get (tc_idx);
-	      if (__glibc_unlikely (mtag_enabled))
-		return tag_new_zero_region (mem, memsize (mem2chunk (mem)));
-
 	      return clear_memory ((INTERNAL_SIZE_T *) mem, tidx2usize (tc_idx));
 	    }
 	}
@@ -3737,9 +3675,6 @@ __libc_calloc (size_t n, size_t elem_size)
 	  void *mem = tcache_get_large (tc_idx, nb);
 	  if (mem != NULL)
 	    {
-	      if (__glibc_unlikely (mtag_enabled))
-	        return tag_new_zero_region (mem, memsize (mem2chunk (mem)));
-
 	      return memset (mem, 0, memsize (mem2chunk (mem)));
 	    }
 	}
diff --git a/sysdeps/aarch64/__mtag_tag_region.S b/sysdeps/aarch64/__mtag_tag_region.S
index bad3193bfe..85e330812e 100644
--- a/sysdeps/aarch64/__mtag_tag_region.S
+++ b/sysdeps/aarch64/__mtag_tag_region.S
@@ -18,8 +18,6 @@
 
 #include <sysdep.h>
 
-#ifdef USE_MTAG
-
 /* Assumptions:
  *
  * ARMv8-a, AArch64, MTE, LP64 ABI.
@@ -107,4 +105,3 @@ L(no_zva_loop):
 	ret
 
 END (__libc_mtag_tag_region)
-#endif /* USE_MTAG */
diff --git a/sysdeps/aarch64/__mtag_tag_zero_region.S b/sysdeps/aarch64/__mtag_tag_zero_region.S
index 3bc6e7301f..1a84b3e4d4 100644
--- a/sysdeps/aarch64/__mtag_tag_zero_region.S
+++ b/sysdeps/aarch64/__mtag_tag_zero_region.S
@@ -18,8 +18,6 @@
 
 #include <sysdep.h>
 
-#ifdef USE_MTAG
-
 /* Assumptions:
  *
  * ARMv8-a, AArch64, MTE, LP64 ABI.
@@ -107,4 +105,3 @@ L(no_zva_loop):
 	ret
 
 END (__libc_mtag_tag_zero_region)
-#endif /* USE_MTAG */
diff --git a/sysdeps/aarch64/cpu-features.h b/sysdeps/aarch64/cpu-features.h
index d6367a4596..f414060066 100644
--- a/sysdeps/aarch64/cpu-features.h
+++ b/sysdeps/aarch64/cpu-features.h
@@ -64,8 +64,7 @@ struct cpu_features
   uint64_t midr_el1;
   unsigned zva_size;
   bool bti;
-  /* Currently, the GLIBC memory tagging tunable only defines 8 bits.  */
-  uint8_t mte_state;
+  uint8_t reserved;
   bool sve;
   bool unused;
   bool mops;
diff --git a/sysdeps/aarch64/libc-mtag.h b/sysdeps/aarch64/libc-mtag.h
index 1d7368b806..663b866bf8 100644
--- a/sysdeps/aarch64/libc-mtag.h
+++ b/sysdeps/aarch64/libc-mtag.h
@@ -19,10 +19,7 @@
 #ifndef _AARCH64_LIBC_MTAG_H
 #define _AARCH64_LIBC_MTAG_H 1
 
-#ifndef USE_MTAG
-/* Generic bindings for systems that do not support memory tagging.  */
-#include_next "libc-mtag.h"
-#else
+#if 0
 
 /* Used to ensure additional alignment when objects need to have distinct
    tags.  */
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
index 36bd72bb12..cda1f82948 100644
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
@@ -20,7 +20,6 @@
 #include <cpu-features.h>
 #include <sys/auxv.h>
 #include <elf/dl-hwcaps.h>
-#include <sys/prctl.h>
 #include <sys/utsname.h>
 #include <dl-tunables-parse.h>
 #include <dl-symbol-redir-ifunc.h>
@@ -96,33 +95,6 @@ init_cpu_features (struct cpu_features *cpu_features)
   if (cpu_features->bti)
     GLRO (dl_aarch64_bti) = TUNABLE_GET (glibc, cpu, aarch64_bti, uint64_t, 0);
 
-  /* Setup memory tagging support if the HW and kernel support it, and if
-     the user has requested it.  */
-  cpu_features->mte_state = 0;
-
-#ifdef USE_MTAG
-  int mte_state = TUNABLE_GET (glibc, mem, tagging, unsigned, 0);
-  cpu_features->mte_state = (GLRO (dl_hwcap2) & HWCAP2_MTE) ? mte_state : 0;
-  /* If we lack the MTE feature, disable the tunable, since it will
-     otherwise cause instructions that won't run on this CPU to be used.  */
-  TUNABLE_SET (glibc, mem, tagging, cpu_features->mte_state);
-
-  if (cpu_features->mte_state & 4)
-    /* Enable choosing system-preferred faulting mode.  */
-    __prctl (PR_SET_TAGGED_ADDR_CTRL,
-	     (PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC
-	      | MTE_ALLOWED_TAGS),
-	     0, 0, 0);
-  else if (cpu_features->mte_state & 2)
-    __prctl (PR_SET_TAGGED_ADDR_CTRL,
-	     (PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | MTE_ALLOWED_TAGS),
-	     0, 0, 0);
-  else if (cpu_features->mte_state)
-    __prctl (PR_SET_TAGGED_ADDR_CTRL,
-	     (PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_ASYNC | MTE_ALLOWED_TAGS),
-	     0, 0, 0);
-#endif
-
   /* Check if SVE is supported.  */
   cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE;
 
-- 
2.47.3



More information about the Libc-alpha mailing list