@@ -22,6 +22,8 @@
#define TUNABLE_NAMESPACE malloc
#include <elf/dl-tunables.h>
+#include <malloc-init.h>
+
/* Compile-time constants. */
#define HEAP_MIN_SIZE (32 * 1024)
@@ -248,6 +250,9 @@ static void tcache_key_initialize (void);
void
__ptmalloc_init (void)
{
+ /* Perform any target-specific initialisation. */
+ ARCH_INIT_MALLOC ();
+
#if USE_TCACHE
tcache_key_initialize ();
#endif
@@ -403,7 +408,7 @@ alloc_new_heap (size_t size, size_t top_pad, size_t pagesize,
}
}
}
- if (__mprotect (p2, size, extra_mmap_prot | PROT_READ | PROT_WRITE) != 0)
+ if (__mprotect (p2, size, extra_mmap_prot) != 0)
{
__munmap (p2, max_size);
return NULL;
@@ -457,7 +462,7 @@ grow_heap (heap_info *h, long diff)
{
if (__mprotect ((char *) h + h->mprotect_size,
(unsigned long) new_size - h->mprotect_size,
- extra_mmap_prot | PROT_READ | PROT_WRITE) != 0)
+ extra_mmap_prot) != 0)
return -2;
h->mprotect_size = new_size;
@@ -1959,9 +1959,7 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags)
size_t padding = MALLOC_ALIGNMENT - CHUNK_HDR_SZ;
size_t size = ALIGN_UP (nb + padding + CHUNK_HDR_SZ, pagesize);
- char *mm = (char *) MMAP (NULL, size,
- extra_mmap_prot | PROT_READ | PROT_WRITE,
- extra_flags);
+ char *mm = (char *) MMAP (NULL, size, extra_mmap_prot, extra_flags);
if (mm == MAP_FAILED)
return mm;
if (extra_flags == 0)
@@ -2000,9 +1998,7 @@ sysmalloc_mmap_fallback (size_t *s, size_t size, size_t minsize,
if (size < minsize)
size = minsize;
- char *mbrk = (char *) (MMAP (NULL, size,
- extra_mmap_prot | PROT_READ | PROT_WRITE,
- extra_flags));
+ char *mbrk = (char *) MMAP (NULL, size, extra_mmap_prot, extra_flags);
if (mbrk == MAP_FAILED)
return MAP_FAILED;
@@ -26,5 +26,6 @@ endif # ifeq ($(subdir),string)
ifeq ($(subdir),malloc)
sysdep_routines += \
malloc-ifuncs \
+ malloc-mte \
# sysdep_routines
endif # ifeq ($(subdir),malloc)
@@ -22,55 +22,59 @@
# if IS_IN (libc)
#include <init-arch.h>
-#include <malloc-api.h>
+#include <malloc-ifuncs.h>
#include <shlib-compat.h>
+#define MTE_ACTIVE (mte && \
+ ((GL (dl_aarch64_mte_scope) & MTE_SCOPE_HEAP) != 0) \
+ && (GL (dl_aarch64_mte_mode) != MTE_MODE_DISABLED))
+
libc_ifunc_hidden (__libc_malloc, __libc_malloc_redirect,
- __libc_malloc)
+ MTE_ACTIVE ? __libc_malloc_mte : __libc_malloc)
strong_alias (__libc_malloc_redirect, malloc)
libc_ifunc_hidden (__libc_calloc, __libc_calloc_redirect,
- __libc_calloc)
+ MTE_ACTIVE ? __libc_calloc_mte : __libc_calloc)
weak_alias (__libc_calloc_redirect, calloc)
libc_ifunc_hidden (__libc_memalign, __libc_memalign_redirect,
- __libc_memalign)
+ MTE_ACTIVE ? __libc_memalign_mte : __libc_memalign)
weak_alias (__libc_memalign_redirect, memalign)
libc_ifunc_hidden (__libc_valloc, __libc_valloc_redirect,
- __libc_valloc)
+ MTE_ACTIVE ? __libc_valloc_mte : __libc_valloc)
weak_alias (__libc_valloc_redirect, valloc)
libc_ifunc_hidden (__libc_pvalloc, __libc_pvalloc_redirect,
- __libc_pvalloc)
+ MTE_ACTIVE ? __libc_pvalloc_mte : __libc_pvalloc)
weak_alias (__libc_pvalloc_redirect, pvalloc)
libc_ifunc_hidden (__libc_realloc, __libc_realloc_redirect,
- __libc_realloc)
+ MTE_ACTIVE ? __libc_realloc_mte : __libc_realloc)
strong_alias (__libc_realloc_redirect, realloc)
libc_ifunc_hidden (__libc_free, __libc_free_redirect,
- __libc_free)
+ MTE_ACTIVE ? __libc_free_mte : __libc_free)
strong_alias (__libc_free_redirect, free)
libc_ifunc_hidden (__malloc_usable_size, __malloc_usable_size_redirect,
- __malloc_usable_size)
+ MTE_ACTIVE ? __malloc_usable_size_mte : __malloc_usable_size)
weak_alias (__malloc_usable_size_redirect, malloc_usable_size)
libc_ifunc_hidden (__posix_memalign, __posix_memalign_redirect,
- __posix_memalign)
+ MTE_ACTIVE ? __posix_memalign_mte : __posix_memalign)
weak_alias (__posix_memalign_redirect, posix_memalign)
libc_ifunc_hidden (__aligned_alloc, __aligned_alloc_redirect,
- __aligned_alloc)
+ MTE_ACTIVE ? __aligned_alloc_mte : __aligned_alloc)
weak_alias (__aligned_alloc_redirect, aligned_alloc)
libc_ifunc_hidden (__free_sized, __free_sized_redirect,
- __free_sized)
+ MTE_ACTIVE ? __free_sized_mte : __free_sized)
weak_alias (__free_sized_redirect, free_sized)
libc_ifunc_hidden (__free_aligned_sized, __free_aligned_sized_redirect,
- __free_aligned_sized)
+ MTE_ACTIVE ? __free_aligned_sized_mte : __free_aligned_sized)
weak_alias (__free_aligned_sized_redirect, free_aligned_sized)
# endif /* IS_IN (libc) */
@@ -22,4 +22,38 @@
/* AArch64 target provides ifuncs for malloc functions. */
#define USE_MULTIARCH_MALLOC 1
+#include <malloc-api.h>
+
+/* MTE implementations of malloc functions. */
+void *__libc_malloc_mte (size_t);
+libc_hidden_proto (__libc_malloc_mte)
+void *__libc_calloc_mte (size_t, size_t);
+libc_hidden_proto (__libc_calloc_mte)
+void *__libc_memalign_mte (size_t, size_t);
+libc_hidden_proto (__libc_memalign_mte)
+void *__libc_valloc_mte (size_t);
+libc_hidden_proto (__libc_valloc_mte)
+void *__libc_pvalloc_mte (size_t);
+libc_hidden_proto (__libc_pvalloc_mte)
+void *__libc_realloc_mte (void *, size_t);
+libc_hidden_proto (__libc_realloc_mte)
+void __libc_free_mte (void *);
+libc_hidden_proto (__libc_free_mte)
+size_t __malloc_usable_size_mte (void *);
+libc_hidden_proto (__malloc_usable_size_mte)
+
+/* For additions of POSIX: MTE version. */
+int __posix_memalign_mte (void **, size_t, size_t);
+libc_hidden_proto (__posix_memalign_mte)
+
+/* For ISO C17: MTE version. */
+void *__aligned_alloc_mte (size_t, size_t);
+libc_hidden_proto (__aligned_alloc_mte)
+
+/* For ISO C23: MTE version. */
+void __free_sized_mte (void *, size_t);
+libc_hidden_proto (__free_sized_mte)
+void __free_aligned_sized_mte (void *, size_t, size_t);
+libc_hidden_proto (__free_aligned_sized_mte)
+
#endif /* _AARCH64_MALLOC_IFUNCS_H */
new file mode 100644
@@ -0,0 +1,33 @@
+/* Definitions for malloc init: aarch64 version.
+ Copyright (C) 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _AARCH64_MALLOC_INIT_H
+#define _AARCH64_MALLOC_INIT_H
+
+#define MTE_ACTIVE ((GL (dl_aarch64_mte_scope) & MTE_SCOPE_HEAP) != 0 \
+ && (GL (dl_aarch64_mte_mode) != MTE_MODE_DISABLED))
+
+#define ARCH_INIT_MALLOC() \
+ extra_mmap_prot = PROT_READ | PROT_WRITE; \
+ if (MTE_ACTIVE) \
+ { \
+ extra_mmap_prot |= PROT_MTE; \
+ __always_fail_morecore = true; \
+ }
+
+#endif /* _AARCH64_MALLOC_INIT_H */
new file mode 100644
@@ -0,0 +1,91 @@
+/* Implementation for MTE (memory tagging) wrappers in malloc.
+ Copyright (C) 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <malloc-ifuncs.h>
+
+void *__libc_malloc_mte (size_t bytes)
+{
+ return __libc_malloc (bytes);
+}
+libc_hidden_def (__libc_malloc_mte)
+
+void *__libc_calloc_mte (size_t n, size_t elem_size)
+{
+ return __libc_calloc (n, elem_size);
+}
+libc_hidden_def (__libc_calloc_mte)
+
+void *__libc_memalign_mte (size_t alignment, size_t bytes)
+{
+ return __libc_memalign (alignment, bytes);
+}
+libc_hidden_def (__libc_memalign_mte)
+
+void *__libc_valloc_mte (size_t bytes)
+{
+ return __libc_valloc (bytes);
+}
+libc_hidden_def (__libc_valloc_mte)
+
+void *__libc_pvalloc_mte (size_t bytes)
+{
+ return __libc_pvalloc (bytes);
+}
+libc_hidden_def (__libc_pvalloc_mte)
+
+void *__libc_realloc_mte (void *oldmem, size_t bytes)
+{
+ return __libc_realloc (oldmem, bytes);
+}
+libc_hidden_def (__libc_realloc_mte)
+
+void __libc_free_mte (void *mem)
+{
+ __libc_free (mem);
+}
+libc_hidden_def (__libc_free_mte)
+
+size_t __malloc_usable_size_mte (void *m)
+{
+ return __malloc_usable_size (m);
+}
+libc_hidden_def (__malloc_usable_size_mte)
+
+int __posix_memalign_mte (void **memptr, size_t alignment, size_t size)
+{
+ return __posix_memalign (memptr, alignment, size);
+}
+libc_hidden_def (__posix_memalign_mte)
+
+void *__aligned_alloc_mte (size_t alignment, size_t bytes)
+{
+ return __aligned_alloc (alignment, bytes);
+}
+libc_hidden_def (__aligned_alloc_mte)
+
+void __free_sized_mte (void *ptr, size_t size)
+{
+ __free_sized (ptr, size);
+}
+libc_hidden_def (__free_sized_mte)
+
+void __free_aligned_sized_mte (void *ptr, size_t alignment, size_t size)
+{
+ __free_aligned_sized (ptr, alignment, size);
+}
+libc_hidden_def (__free_aligned_sized_mte)
new file mode 100644
@@ -0,0 +1,25 @@
+/* Definition for malloc init: generic version.
+ Copyright (C) 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _GENERIC_MALLOC_INIT_H
+#define _GENERIC_MALLOC_INIT_H
+
+#define ARCH_INIT_MALLOC() \
+ extra_mmap_prot = PROT_READ | PROT_WRITE;
+
+#endif /* _GENERIC_MALLOC_INIT_H */
@@ -394,6 +394,22 @@ ifeq ($(subdir),stdlib)
gen-as-const-headers += ucontext_i.sym
endif
+ifeq ($(subdir),malloc)
+# Add MTE tunable to all malloc tests except malloc-check and mcheck variants
+tests-malloc-mte = \
+ $(tests) \
+ $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1) \
+ $(tests-malloc-hugetlb2:%=%-malloc-hugetlb2) \
+ $(tests-malloc-largetcache:%=%-malloc-largetcache) \
+ # tests-malloc-mte
+
+define tests-malloc-mte-ENVS
+$(1)-TUNABLES += glibc.cpu.mtemode=sync
+endef
+
+$(foreach t,$(tests-malloc-mte),$(eval $(call tests-malloc-mte-ENVS,$(t))))
+endif # ifeq ($(subdir),malloc)
+
abi-variants := lp64
abi-variants += lp64_be