[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