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

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed May 20 20:28:08 GMT 2026



On 20/05/26 10:27, Yury Khrustalev wrote:
> 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.

LGTM, thanks. I think maybe it would be better to just squash all
the patches in only one.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
>  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 5313ee68e3..d7224f775c 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;
>  }
>  
> @@ -1258,23 +1246,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);
>  }
>  
> @@ -1377,25 +1348,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;
>  }
>  
> @@ -2228,7 +2185,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;
> @@ -2269,7 +2226,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;
> @@ -3296,11 +3253,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.  */
> @@ -3368,11 +3320,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);
>  
> @@ -3668,12 +3615,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 */
> @@ -3720,9 +3661,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));
>  	    }
>  	}
> @@ -3732,9 +3670,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;
>  



More information about the Libc-alpha mailing list