[PATCH v2 3/3] malloc: Remove currently broken memory tagging

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed May 20 20:30:13 GMT 2026



On 20/05/26 10:27, Yury Khrustalev wrote:
> Remove AArch64-specific code, that is currently broken, from the
> core malloc implementation.
> 
> Code clean-up, no functional change unrelated to memory tagging.

Why keep the MTE code if it is unused now?

> ---
>  malloc/malloc-check.c                         |  30 ++--
>  malloc/malloc.c                               | 163 ++----------------
>  sysdeps/aarch64/Makefile                      |   9 +-
>  ...__mtag_tag_region.S => __mte_tag_region.S} |   4 +-
>  ..._zero_region.S => __mte_tag_region_zero.S} |   4 +-
>  .../aarch64/{libc-mtag.h => aarch64-mte.h}    |  70 ++++----
>  sysdeps/generic/libc-mtag.h                   |  73 --------
>  7 files changed, 70 insertions(+), 283 deletions(-)
>  rename sysdeps/aarch64/{__mtag_tag_region.S => __mte_tag_region.S} (97%)
>  rename sysdeps/aarch64/{__mtag_tag_zero_region.S => __mte_tag_region_zero.S} (97%)
>  rename sysdeps/aarch64/{libc-mtag.h => aarch64-mte.h} (57%)
>  delete mode 100644 sysdeps/generic/libc-mtag.h
> 
> diff --git a/malloc/malloc-check.c b/malloc/malloc-check.c
> index ae5025d69a..8ed419c6e9 100644
> --- a/malloc/malloc-check.c
> +++ b/malloc/malloc-check.c
> @@ -19,12 +19,8 @@
>  #define __mremap mremap
>  #include "malloc.c"
>  
> -/* When memory is tagged, the checking data is stored in the user part
> -   of the chunk.  We can't rely on the user not having modified the
> -   tags, so fetch the tag at each location before dereferencing
> -   it.  */
> -#define SAFE_CHAR_OFFSET(p,offset) \
> -  ((unsigned char *) tag_at (((unsigned char *) p) + offset))
> +#define CHAR_OFFSET(p,offset) \
> +  ((unsigned char *) (((unsigned char *) p) + offset))
>  
>  /* A simple, standard set of debugging hooks.  Overhead is `only' one
>     byte per chunk; still this will catch most cases of double frees or
> @@ -58,7 +54,7 @@ malloc_check_get_size (void *mem)
>    unsigned char magic = magicbyte (p);
>  
>    for (size = CHUNK_HDR_SZ + memsize (p) - 1;
> -       (c = *SAFE_CHAR_OFFSET (p, size)) != magic;
> +       (c = *CHAR_OFFSET (p, size)) != magic;
>         size -= c)
>      {
>        if (c <= 0 || size < (c + CHUNK_HDR_SZ))
> @@ -95,9 +91,9 @@ mem2mem_check (void *ptr, size_t req_sz)
>        if (block_sz == magic)
>          --block_sz;
>  
> -      *SAFE_CHAR_OFFSET (m_ptr, i) = block_sz;
> +      *CHAR_OFFSET (m_ptr, i) = block_sz;
>      }
> -  *SAFE_CHAR_OFFSET (m_ptr, req_sz) = magic;
> +  *CHAR_OFFSET (m_ptr, req_sz) = magic;
>    return (void *) m_ptr;
>  }
>  
> @@ -131,7 +127,7 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
>          return NULL;
>  
>        for (sz = CHUNK_HDR_SZ + memsize (p) - 1;
> -	   (c = *SAFE_CHAR_OFFSET (p, sz)) != magic;
> +	   (c = *CHAR_OFFSET (p, sz)) != magic;
>  	   sz -= c)
>          {
>            if (c == 0 || sz < (c + CHUNK_HDR_SZ))
> @@ -156,7 +152,7 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
>          return NULL;
>  
>        for (sz = CHUNK_HDR_SZ + memsize (p) - 1;
> -	   (c = *SAFE_CHAR_OFFSET (p, sz)) != magic;
> +	   (c = *CHAR_OFFSET (p, sz)) != magic;
>  	   sz -= c)
>          {
>            if (c == 0 || sz < (c + CHUNK_HDR_SZ))
> @@ -164,7 +160,7 @@ mem2chunk_check (void *mem, unsigned char **magic_p)
>          }
>      }
>  
> -  unsigned char* safe_p = SAFE_CHAR_OFFSET (p, sz);
> +  unsigned char* safe_p = CHAR_OFFSET (p, sz);
>    *safe_p ^= 0xFF;
>    if (magic_p)
>      *magic_p = safe_p;
> @@ -204,7 +200,7 @@ malloc_check (size_t sz)
>    top_check ();
>    victim = _int_malloc (&main_arena, nb);
>    __libc_lock_unlock (main_arena.mutex);
> -  return mem2mem_check (tag_new_usable (victim), sz);
> +  return mem2mem_check (victim, sz);
>  }
>  
>  static void
> @@ -228,8 +224,6 @@ free_check (void *mem)
>      }
>    else
>      {
> -      /* Mark the chunk as belonging to the library again.  */
> -      (void)tag_region (chunk2mem (p), memsize (p));
>        _int_free_chunk (&main_arena, p, chunksize (p), 1);
>        __libc_lock_unlock (main_arena.mutex);
>      }
> @@ -278,7 +272,7 @@ realloc_check (void *oldmem, size_t bytes)
>  #if HAVE_MREMAP
>        mchunkptr newp = mremap_chunk (oldp, chnb);
>        if (newp)
> -        newmem = chunk2mem_tag (newp);
> +        newmem = chunk2mem (newp);
>        else
>  #endif
>        {
> @@ -313,7 +307,7 @@ invert:
>  
>    __libc_lock_unlock (main_arena.mutex);
>  
> -  return mem2mem_check (tag_new_usable (newmem), bytes);
> +  return mem2mem_check (newmem, bytes);
>  }
>  
>  static void *
> @@ -355,7 +349,7 @@ memalign_check (size_t alignment, size_t bytes)
>    top_check ();
>    mem = _int_memalign (&main_arena, alignment, bytes + 1);
>    __libc_lock_unlock (main_arena.mutex);
> -  return mem2mem_check (tag_new_usable (mem), bytes);
> +  return mem2mem_check (mem, bytes);
>  }
>  
>  static void
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index d7224f775c..c1e1a9c659 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -233,9 +233,7 @@
>  /* For ALIGN_UP et. al.  */
>  #include <libc-pointer-arith.h>
>  
> -/* For memory tagging.  */
> -#include <libc-mtag.h>
> -
> +/* For internal malloc interfaces and declarations.  */
>  #include <malloc/malloc-internal.h>
>  
>  /* For SINGLE_THREAD_P.  */
> @@ -349,86 +347,8 @@ verify (PTRDIFF_MAX <= SIZE_MAX / 2);
>  #define MORECORE         (*__glibc_morecore)
>  #define MORECORE_FAILURE  NULL
>  
> -/* Memory tagging.  */
> -
> -/* Some systems support the concept of tagging (sometimes known as
> -   coloring) memory locations on a fine grained basis.  Each memory
> -   location is given a color (normally allocated randomly) and
> -   pointers are also colored.  When the pointer is dereferenced, the
> -   pointer's color is checked against the memory's color and if they
> -   differ the access is faulted (sometimes lazily).
> -
> -   We use this in glibc by maintaining a single color for the malloc
> -   data structures that are interleaved with the user data and then
> -   assigning separate colors for each block allocation handed out.  In
> -   this way simple buffer overruns will be rapidly detected.  When
> -   memory is freed, the memory is recolored back to the glibc default
> -   so that simple use-after-free errors can also be detected.
> -
> -   If memory is reallocated the buffer is recolored even if the
> -   address remains the same.  This has a performance impact, but
> -   guarantees that the old pointer cannot mistakenly be reused (code
> -   that compares old against new will see a mismatch and will then
> -   need to behave as though realloc moved the data to a new location).
> -
> -   Internal API for memory tagging support.
> -
> -   The aim is to keep the code for memory tagging support as close to
> -   the normal APIs in glibc as possible, so that if tagging is not
> -   enabled in the library, or is disabled at runtime then standard
> -   operations can continue to be used.  Support macros are used to do
> -   this:
> -
> -   void *tag_new_zero_region (void *ptr, size_t size)
> -
> -   Allocates a new tag, colors the memory with that tag, zeros the
> -   memory and returns a pointer that is correctly colored for that
> -   location.  The non-tagging version will simply call memset with 0.
> -
> -   void *tag_region (void *ptr, size_t size)
> -
> -   Color the region of memory pointed to by PTR and size SIZE with
> -   the color of PTR.  Returns the original pointer.
> -
> -   void *tag_new_usable (void *ptr)
> -
> -   Allocate a new random color and use it to color the user region of
> -   a chunk; this may include data from the subsequent chunk's header
> -   if tagging is sufficiently fine grained.  Returns PTR suitably
> -   recolored for accessing the memory there.
> -
> -   void *tag_at (void *ptr)
> -
> -   Read the current color of the memory at the address pointed to by
> -   PTR (ignoring it's current color) and return PTR recolored to that
> -   color.  PTR must be valid address in all other respects.  When
> -   tagging is not enabled, it simply returns the original pointer.
> -*/
> -
>  static int extra_mmap_prot = 0;
>  
> -static __always_inline void *
> -tag_region (void *ptr, size_t size)
> -{
> -  return ptr;
> -}
> -
> -static __always_inline void *
> -tag_new_zero_region (void *ptr, size_t size)
> -{
> -  return memset (ptr, 0, size);
> -}
> -
> -/* Defined later.  */
> -static void *
> -tag_new_usable (void *ptr);
> -
> -static __always_inline void *
> -tag_at (void *ptr)
> -{
> -  return ptr;
> -}
> -
>  
>  /*
>    MORECORE-related declarations. By default, rely on sbrk
> @@ -1182,38 +1102,15 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
>    ---------- Size and alignment checks and conversions ----------
>  */
>  
> -/* Conversion from malloc headers to user pointers, and back.  When
> -   using memory tagging the user data and the malloc data structure
> -   headers have distinct tags.  Converting fully from one to the other
> -   involves extracting the tag at the other address and creating a
> -   suitable pointer using it.  That can be quite expensive.  There are
> -   cases when the pointers are not dereferenced (for example only used
> -   for alignment check) so the tags are not relevant, and there are
> -   cases when user data is not tagged distinctly from malloc headers
> -   (user data is untagged because tagging is done late in malloc and
> -   early in free).  User memory tagging across internal interfaces:
> -
> -      sysmalloc: Returns untagged memory.
> -      _int_malloc: Returns untagged memory.
> -      _int_memalign: Returns untagged memory.
> -      _int_memalign: Returns untagged memory.
> -      _mid_memalign: Returns tagged memory.
> -      _int_realloc: Takes and returns tagged memory.
> -*/
> -
>  /* The chunk header is two SIZE_SZ elements, but this is used widely, so
>     we define it here for clarity later.  */
>  #define CHUNK_HDR_SZ (2 * SIZE_SZ)
>  
> -/* Convert a chunk address to a user mem pointer without correcting
> -   the tag.  */
> +/* Convert a chunk address to a user mem pointer.  */
>  #define chunk2mem(p) ((void*)((char*)(p) + CHUNK_HDR_SZ))
>  
> -/* Convert a chunk address to a user mem pointer and extract the right tag.  */
> -#define chunk2mem_tag(p) ((void*)tag_at ((char*)(p) + CHUNK_HDR_SZ))
> -
> -/* Convert a user mem pointer to a chunk address and extract the right tag.  */
> -#define mem2chunk(mem) ((mchunkptr)tag_at (((char*)(mem) - CHUNK_HDR_SZ)))
> +/* Convert a user mem pointer to a chunk address.  */
> +#define mem2chunk(mem) ((mchunkptr) (((char*)(mem) - CHUNK_HDR_SZ)))
>  
>  /* The smallest possible chunk */
>  #define MIN_CHUNK_SIZE        (offsetof(struct malloc_chunk, fd_nextsize))
> @@ -1350,12 +1247,6 @@ checked_request2size (size_t req) __nonnull (1)
>     dumped heap chunks.  */
>  #define memsize(p) (chunksize (p) - CHUNK_HDR_SZ + SIZE_SZ)
>  
> -static __always_inline void *
> -tag_new_usable (void *ptr)
> -{
> -  return ptr;
> -}
> -
>  /* Huge page used for an mmap chunk.  */
>  #define MMAP_HP 0x1
>  
> @@ -3063,7 +2954,7 @@ tcache_get_align (size_t nb, size_t alignment)
>        if (te != NULL
>  	  && csize == nb
>  	  && PTR_IS_ALIGNED (te, alignment))
> -	return tag_new_usable (tcache_get_n (tc_idx, tep, mangled));
> +	return tcache_get_n (tc_idx, tep, mangled);
>      }
>    return NULL;
>  }
> @@ -3181,7 +3072,7 @@ __libc_malloc2 (size_t bytes)
>  
>    if (SINGLE_THREAD_P)
>      {
> -      victim = tag_new_usable (_int_malloc (&main_arena, bytes));
> +      victim = _int_malloc (&main_arena, bytes);
>        assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
>  	      &main_arena == arena_for_chunk (mem2chunk (victim)));
>        return victim;
> @@ -3202,8 +3093,6 @@ __libc_malloc2 (size_t bytes)
>    if (ar_ptr != NULL)
>      __libc_lock_unlock (ar_ptr->mutex);
>  
> -  victim = tag_new_usable (victim);
> -
>    assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
>            ar_ptr == arena_for_chunk (mem2chunk (victim)));
>    return victim;
> @@ -3222,14 +3111,14 @@ __libc_malloc (size_t bytes)
>        if (__glibc_likely (tc_idx < TCACHE_SMALL_BINS))
>          {
>  	  if (tcache->entries[tc_idx] != NULL)
> -	    return tag_new_usable (tcache_get (tc_idx));
> +	    return tcache_get (tc_idx);
>  	}
>        else
>          {
>  	  tc_idx = large_csize2tidx (nb);
>  	  void *victim = tcache_get_large (tc_idx, nb);
>  	  if (victim != NULL)
> -	    return tag_new_usable (victim);
> +	    return victim;
>  	}
>      }
>  #endif
> @@ -3255,9 +3144,6 @@ __libc_free (void *mem)
>  
>    p = mem2chunk (mem);
>  
> -  /* Mark the chunk as belonging to the library again.  */
> -  tag_region (chunk2mem (p), memsize (p));
> -
>    INTERNAL_SIZE_T size = chunksize (p);
>  
>    if (__glibc_unlikely (misaligned_chunk (p)))
> @@ -3361,15 +3247,7 @@ __libc_realloc (void *oldmem, size_t bytes)
>  #if HAVE_MREMAP
>        newp = mremap_chunk (oldp, nb);
>        if (newp)
> -	{
> -	  void *newmem = chunk2mem_tag (newp);
> -	  /* Give the new block a different tag.  This helps to ensure
> -	     that stale handles to the previous mapping are not
> -	     reused.  There's a performance hit for both us and the
> -	     caller for doing this, so we might want to
> -	     reconsider.  */
> -	  return tag_new_usable (newmem);
> -	}
> +	return chunk2mem (newp);
>  #endif
>        /* Return if shrinking and mremap was unsuccessful.  */
>        if (bytes <= usable)
> @@ -3411,10 +3289,8 @@ __libc_realloc (void *oldmem, size_t bytes)
>        newp = __libc_malloc (bytes);
>        if (newp != NULL)
>          {
> -	  size_t sz = memsize (oldp);
> -	  memcpy (newp, oldmem, sz);
> -	  (void) tag_region (chunk2mem (oldp), sz);
> -          _int_free_chunk (ar_ptr, oldp, chunksize (oldp), 0);
> +	  memcpy (newp, oldmem, memsize (oldp));
> +	  _int_free_chunk (ar_ptr, oldp, chunksize (oldp), 0);
>          }
>      }
>  
> @@ -3498,7 +3374,7 @@ _mid_memalign (size_t alignment, size_t bytes)
>  #if USE_TCACHE
>    void *victim = tcache_get_align (checked_request2size (bytes), alignment);
>    if (victim != NULL)
> -    return tag_new_usable (victim);
> +    return victim;
>  #endif
>  
>    if (SINGLE_THREAD_P)
> @@ -3506,7 +3382,7 @@ _mid_memalign (size_t alignment, size_t bytes)
>        p = _int_memalign (&main_arena, alignment, bytes);
>        assert (!p || chunk_is_mmapped (mem2chunk (p)) ||
>  	      &main_arena == arena_for_chunk (mem2chunk (p)));
> -      return tag_new_usable (p);
> +      return p;
>      }
>  
>    arena_get (ar_ptr, bytes + alignment + MINSIZE);
> @@ -3524,7 +3400,7 @@ _mid_memalign (size_t alignment, size_t bytes)
>  
>    assert (!p || chunk_is_mmapped (mem2chunk (p)) ||
>            ar_ptr == arena_for_chunk (mem2chunk (p)));
> -  return tag_new_usable (p);
> +  return p;
>  }
>  
>  void *
> @@ -4429,7 +4305,7 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
>            av->top = chunk_at_offset (oldp, nb);
>            set_head (av->top, (newsize - nb) | PREV_INUSE);
>            check_inuse_chunk (av, oldp);
> -          return tag_new_usable (chunk2mem (oldp));
> +          return chunk2mem (oldp);
>          }
>  
>        /* Try to expand forward into next chunk;  split off remainder below */
> @@ -4463,10 +4339,7 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
>            else
>              {
>  	      void *oldmem = chunk2mem (oldp);
> -	      size_t sz = memsize (oldp);
> -	      (void) tag_region (oldmem, sz);
> -	      newmem = tag_new_usable (newmem);
> -	      memcpy (newmem, oldmem, sz);
> +	      memcpy (newmem, oldmem, memsize (oldp));
>  	      _int_free_chunk (av, oldp, chunksize (oldp), 1);
>  	      check_inuse_chunk (av, newp);
>  	      return newmem;
> @@ -4488,8 +4361,6 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
>    else   /* split remainder */
>      {
>        remainder = chunk_at_offset (newp, nb);
> -      /* Clear any user-space tags before writing the header.  */
> -      remainder = tag_region (remainder, remainder_size);
>        set_head_size (newp, nb | (av != &main_arena ? NON_MAIN_ARENA : 0));
>        set_head (remainder, remainder_size | PREV_INUSE |
>                  (av != &main_arena ? NON_MAIN_ARENA : 0));
> @@ -4499,7 +4370,7 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
>      }
>  
>    check_inuse_chunk (av, newp);
> -  return tag_new_usable (chunk2mem (newp));
> +  return chunk2mem (newp);
>  }
>  
>  /*
> diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
> index 2cf2903021..52ac85a75d 100644
> --- a/sysdeps/aarch64/Makefile
> +++ b/sysdeps/aarch64/Makefile
> @@ -82,8 +82,8 @@ sysdep_headers += \
>  sysdep_routines += \
>    __alloc_gcs \
>    __arm_za_disable \
> -  __mtag_tag_region \
> -  __mtag_tag_zero_region \
> +  __mte_tag_region \
> +  __mte_tag_region_zero \
>    # sysdep_routines
>  
>  tests += \
> @@ -104,10 +104,7 @@ $(objpfx)tst-sme-za-disable-fail: $(objpfx)__arm_za_disable.o
>  endif
>  
>  ifeq ($(subdir),malloc)
> -sysdep_malloc_debug_routines = \
> -  __mtag_tag_region \
> -  __mtag_tag_zero_region \
> -  # sysdep_malloc_debug_routines
> +
>  endif # malloc directory
>  
>  ifeq ($(subdir),support)
> diff --git a/sysdeps/aarch64/__mtag_tag_region.S b/sysdeps/aarch64/__mte_tag_region.S
> similarity index 97%
> rename from sysdeps/aarch64/__mtag_tag_region.S
> rename to sysdeps/aarch64/__mte_tag_region.S
> index 85e330812e..1698489fc2 100644
> --- a/sysdeps/aarch64/__mtag_tag_region.S
> +++ b/sysdeps/aarch64/__mte_tag_region.S
> @@ -37,7 +37,7 @@
>  #define tmp	x4
>  #define zva_val	x4
>  
> -ENTRY (__libc_mtag_tag_region)
> +ENTRY (__mte_tag_region)
>  	add	dstend, dstin, count
>  
>  	cmp	count, 96
> @@ -104,4 +104,4 @@ L(no_zva_loop):
>  	st2g	dstin, [dstend, -32]
>  	ret
>  
> -END (__libc_mtag_tag_region)
> +END (__mte_tag_region)
> diff --git a/sysdeps/aarch64/__mtag_tag_zero_region.S b/sysdeps/aarch64/__mte_tag_region_zero.S
> similarity index 97%
> rename from sysdeps/aarch64/__mtag_tag_zero_region.S
> rename to sysdeps/aarch64/__mte_tag_region_zero.S
> index 1a84b3e4d4..2f506c9ee8 100644
> --- a/sysdeps/aarch64/__mtag_tag_zero_region.S
> +++ b/sysdeps/aarch64/__mte_tag_region_zero.S
> @@ -37,7 +37,7 @@
>  #define tmp	x4
>  #define zva_val	x4
>  
> -ENTRY (__libc_mtag_tag_zero_region)
> +ENTRY (__mte_tag_region_zero)
>  	add	dstend, dstin, count
>  
>  	cmp	count, 96
> @@ -104,4 +104,4 @@ L(no_zva_loop):
>  	stz2g	dstin, [dstend, -32]
>  	ret
>  
> -END (__libc_mtag_tag_zero_region)
> +END (__mte_tag_region_zero)
> diff --git a/sysdeps/aarch64/libc-mtag.h b/sysdeps/aarch64/aarch64-mte.h
> similarity index 57%
> rename from sysdeps/aarch64/libc-mtag.h
> rename to sysdeps/aarch64/aarch64-mte.h
> index 663b866bf8..f42564f528 100644
> --- a/sysdeps/aarch64/libc-mtag.h
> +++ b/sysdeps/aarch64/aarch64-mte.h
> @@ -1,4 +1,4 @@
> -/* libc-internal interface for tagged (colored) memory support.
> +/* AArch64 MTE (Memory Tagging Extension) declarations.
>     Copyright (C) 2020-2026 Free Software Foundation, Inc.
>     This file is part of the GNU C Library.
>  
> @@ -16,51 +16,49 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> -#ifndef _AARCH64_LIBC_MTAG_H
> -#define _AARCH64_LIBC_MTAG_H 1
> +#ifndef _AARCH64_MTE_H
> +#define _AARCH64_MTE_H 1
>  
> -#if 0
> +#include <stddef.h>
> +#include <stdint.h>
> +#include <sys/cdefs.h>
>  
> -/* Used to ensure additional alignment when objects need to have distinct
> -   tags.  */
> -#define __MTAG_GRANULE_SIZE 16
> -
> -/* Non-zero if memory obtained via morecore (sbrk) is not tagged.  */
> -#define __MTAG_SBRK_UNTAGGED 1
> -
> -/* Extra flags to pass to mmap to get tagged pages.  */
> -#define __MTAG_MMAP_FLAGS PROT_MTE
> -
> -/* Set the tags for a region of memory, which must have size and alignment
> -   that are multiples of __MTAG_GRANULE_SIZE.  Size cannot be zero.  */
> -void *__libc_mtag_tag_region (void *, size_t);
> -
> -/* Optimized equivalent to __libc_mtag_tag_region followed by memset to 0.  */
> -void *__libc_mtag_tag_zero_region (void *, size_t);
> -
> -/* Convert address P to a pointer that is tagged correctly for that
> -   location.  */
> -static __always_inline void *
> -__libc_mtag_address_get_tag (void *p)
> +/* Assign a new (random) tag to a pointer P (does not adjust the
> +   allocation tag on the memory addressed).  */
> +static __always_inline __attribute_maybe_unused__ void *
> +__mte_new_tag (void *p)
>  {
>    register void *x0 asm ("x0") = p;
> -  asm (".inst 0xd9600000 /* ldg x0, [x0] */" : "+r" (x0));
> +  register uintptr_t x1 asm ("x1");
> +  /* Guarantee that the new tag is not the same as now.  */
> +  asm (".inst 0x9adf1401 /* gmi x1, x0, xzr */\n"
> +       ".inst 0x9ac11000 /* irg x0, x0, x1 */" : "+r" (x0), "=r" (x1));
>    return x0;
>  }
>  
> -/* Assign a new (random) tag to a pointer P (does not adjust the tag on
> -   the memory addressed).  */
> -static __always_inline void *
> -__libc_mtag_new_tag (void *p)
> +/* Clears logical tag in the input pointer.  */
> +static __always_inline __attribute_maybe_unused__ void *
> +__mte_clear_tag (void *p)
> +{
> +  return (void *)((uintptr_t)p & ~(0xfull << 56ull));
> +}
> +
> +/* Convert address P to a pointer that is tagged correctly for that
> +   location (logical tag in the returned pointer will be the same
> +   as the allocation tag in the addressed memory).  */
> +static __always_inline __attribute_maybe_unused__ void *
> +__mte_get_tag (void *p)
>  {
>    register void *x0 asm ("x0") = p;
> -  register unsigned long x1 asm ("x1");
> -  /* Guarantee that the new tag is not the same as now.  */
> -  asm (".inst 0x9adf1401 /* gmi x1, x0, xzr */\n"
> -       ".inst 0x9ac11000 /* irg x0, x0, x1 */" : "+r" (x0), "=r" (x1));
> +  asm (".inst 0xd9600000 /* ldg x0, [x0] */" : "+r" (x0));
>    return x0;
>  }
>  
> -#endif /* USE_MTAG */
> +/* Set the tags for a region of memory, which must have size and alignment
> +   that are multiples of MTE_GRANULE_SIZE.  Size cannot be zero.  */
> +void *__mte_tag_region (void *, size_t);
> +
> +/* Optimized equivalent to __mte_tag_region followed by memset to 0.  */
> +void *__mte_tag_region_zero (void *, size_t);
>  
> -#endif /* _AARCH64_LIBC_MTAG_H */
> +#endif /* _AARCH64_MTE_H */

It is not clear to me why keep these definitions since they are dead code now.

> diff --git a/sysdeps/generic/libc-mtag.h b/sysdeps/generic/libc-mtag.h
> deleted file mode 100644
> index 5477bfa17f..0000000000
> --- a/sysdeps/generic/libc-mtag.h
> +++ /dev/null
> @@ -1,73 +0,0 @@
> -/* libc-internal interface for tagged (colored) memory support.
> -   Copyright (C) 2020-2026 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -
> -   The GNU C Library is free software; you can redistribute it and/or
> -   modify it under the terms of the GNU Lesser General Public
> -   License as published by the Free Software Foundation; either
> -   version 2.1 of the License, or (at your option) any later version.
> -
> -   The GNU C Library is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> -   Lesser General Public License for more details.
> -
> -   You should have received a copy of the GNU Lesser General Public
> -   License along with the GNU C Library; if not, see
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#ifndef _GENERIC_LIBC_MTAG_H
> -#define _GENERIC_LIBC_MTAG_H 1
> -
> -/* Generic bindings for systems that do not support memory tagging.  */
> -
> -/* Used to ensure additional alignment when objects need to have distinct
> -   tags.  */
> -#define __MTAG_GRANULE_SIZE 1
> -
> -/* Non-zero if memory obtained via morecore (sbrk) is not tagged.  */
> -#define __MTAG_SBRK_UNTAGGED 0
> -
> -/* Extra flags to pass to mmap() to request a tagged region of memory.  */
> -#define __MTAG_MMAP_FLAGS 0
> -
> -/* Memory tagging target hooks are only called when memory tagging is
> -   enabled at runtime.  The generic definitions here must not be used.  */
> -void __libc_mtag_link_error (void);
> -
> -/* Set the tags for a region of memory, which must have size and alignment
> -   that are multiples of __MTAG_GRANULE_SIZE.  Size cannot be zero.  */
> -static inline void *
> -__libc_mtag_tag_region (void *p, size_t n)
> -{
> -  __libc_mtag_link_error ();
> -  return p;
> -}
> -
> -/* Optimized equivalent to __libc_mtag_tag_region followed by memset to 0.  */
> -static inline void *
> -__libc_mtag_tag_zero_region (void *p, size_t n)
> -{
> -  __libc_mtag_link_error ();
> -  return memset (p, 0, n);
> -}
> -
> -/* Convert address P to a pointer that is tagged correctly for that
> -   location.  */
> -static inline void *
> -__libc_mtag_address_get_tag (void *p)
> -{
> -  __libc_mtag_link_error ();
> -  return p;
> -}
> -
> -/* Assign a new (random) tag to a pointer P (does not adjust the tag on
> -   the memory addressed).  */
> -static inline void *
> -__libc_mtag_new_tag (void *p)
> -{
> -  __libc_mtag_link_error ();
> -  return p;
> -}
> -
> -#endif /* _GENERIC_LIBC_MTAG_H */



More information about the Libc-alpha mailing list