diff options
author | jmbills <jason.m.bills@intel.com> | 2021-08-31 21:23:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-31 21:23:16 +0300 |
commit | 04cd92067d2481643df5010cb39b2134b648cf4d (patch) | |
tree | d98626c9763ad9048ac9bfd8269e12eced18d496 /poky/meta/recipes-core/glibc | |
parent | 10ad77d5bc86709d8ff7f95e7040e39f1c153903 (diff) | |
parent | 6f106a0a4ce15fe0678d4ffefd572e6978c72597 (diff) | |
download | openbmc-04cd92067d2481643df5010cb39b2134b648cf4d.tar.xz |
Update
Diffstat (limited to 'poky/meta/recipes-core/glibc')
5 files changed, 1321 insertions, 1 deletions
diff --git a/poky/meta/recipes-core/glibc/glibc-testsuite_2.33.bb b/poky/meta/recipes-core/glibc/glibc-testsuite_2.33.bb index d887aeff7..659d3132f 100644 --- a/poky/meta/recipes-core/glibc/glibc-testsuite_2.33.bb +++ b/poky/meta/recipes-core/glibc/glibc-testsuite_2.33.bb @@ -61,3 +61,4 @@ addtask do_check after do_compile inherit nopackages deltask do_stash_locale deltask do_install +deltask do_populate_sysroot diff --git a/poky/meta/recipes-core/glibc/glibc/mte-backports.patch b/poky/meta/recipes-core/glibc/glibc/mte-backports.patch new file mode 100644 index 000000000..d9604fdf4 --- /dev/null +++ b/poky/meta/recipes-core/glibc/glibc/mte-backports.patch @@ -0,0 +1,1238 @@ +Backport a number of patches from master to improve Arm MTE support. + +Upstream-Status: Backport [will be in 2.34] +Signed-off-by: Ross Burton <ross.burton@arm.com> + +From 2643466c2928a93de7b80a61f6a8f61a653862e1 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Thu, 11 Mar 2021 14:09:56 +0000 +Subject: [PATCH 01/11] malloc: Fix a potential realloc issue with memory + tagging + +At an _int_free call site in realloc the wrong size was used for tag +clearing: the chunk header of the next chunk was also cleared which +in practice may work, but logically wrong. + +The tag clearing is moved before the memcpy to save a tag computation, +this avoids a chunk2mem. Another chunk2mem is removed because newmem +does not have to be recomputed. Whitespaces got fixed too. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/malloc.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 8f8f12c276..51cec67e55 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -4851,14 +4851,14 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + } + else + { +- void *oldmem = chunk2mem (oldp); ++ void *oldmem = chunk2rawmem (oldp); ++ size_t sz = CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ; ++ (void) TAG_REGION (oldmem, sz); + newmem = TAG_NEW_USABLE (newmem); +- memcpy (newmem, oldmem, +- CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ); +- (void) TAG_REGION (chunk2rawmem (oldp), oldsize); +- _int_free (av, oldp, 1); +- check_inuse_chunk (av, newp); +- return chunk2mem (newp); ++ memcpy (newmem, oldmem, sz); ++ _int_free (av, oldp, 1); ++ check_inuse_chunk (av, newp); ++ return newmem; + } + } + } +-- +2.25.1 + + +From 32f3132be063e4b16a5cdb058980af354126e2f4 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Thu, 28 Jan 2021 17:34:36 +0000 +Subject: [PATCH 02/11] malloc: Move MTAG_MMAP_FLAGS definition + +This is only used internally in malloc.c, the extern declaration +was wrong, __mtag_mmap_flags has internal linkage. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + include/malloc.h | 7 ------- + malloc/malloc.c | 2 ++ + 2 files changed, 2 insertions(+), 7 deletions(-) + +diff --git a/include/malloc.h b/include/malloc.h +index 7ae08d53d3..b77761f74d 100644 +--- a/include/malloc.h ++++ b/include/malloc.h +@@ -16,11 +16,4 @@ typedef struct malloc_state *mstate; + + # endif /* !_ISOMAC */ + +-#ifdef USE_MTAG +-extern int __mtag_mmap_flags; +-#define MTAG_MMAP_FLAGS __mtag_mmap_flags +-#else +-#define MTAG_MMAP_FLAGS 0 +-#endif +- + #endif +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 51cec67e55..61c25d0f93 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -463,11 +463,13 @@ static void *(*__tag_region)(void *, size_t) = __default_tag_region; + static void *(*__tag_new_usable)(void *) = __default_tag_nop; + static void *(*__tag_at)(void *) = __default_tag_nop; + ++# define MTAG_MMAP_FLAGS __mtag_mmap_flags + # define TAG_NEW_MEMSET(ptr, val, size) __tag_new_memset (ptr, val, size) + # define TAG_REGION(ptr, size) __tag_region (ptr, size) + # define TAG_NEW_USABLE(ptr) __tag_new_usable (ptr) + # define TAG_AT(ptr) __tag_at (ptr) + #else ++# define MTAG_MMAP_FLAGS 0 + # define TAG_NEW_MEMSET(ptr, val, size) memset (ptr, val, size) + # define TAG_REGION(ptr, size) (ptr) + # define TAG_NEW_USABLE(ptr) (ptr) +-- +2.25.1 + + +From 4b13f77fb97f9618a7868ab767d05e0c2d7c6f6f Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Thu, 4 Feb 2021 11:38:23 +0000 +Subject: [PATCH 03/11] malloc: Simplify __mtag_tag_new_usable + +The chunk cannot be a dumped one here. The only non-obvious cases +are free and realloc which may be called on a dumped area chunk, +but in both cases it can be verified that tagging is already +avoided for dumped area chunks. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/arena.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/malloc/arena.c b/malloc/arena.c +index bf17be27d4..0777dc70c6 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -298,11 +298,6 @@ __mtag_tag_new_usable (void *ptr) + if (ptr) + { + mchunkptr cp = mem2chunk(ptr); +- /* This likely will never happen, but we can't handle retagging +- chunks from the dumped main arena. So just return the +- existing pointer. */ +- if (DUMPED_MAIN_ARENA_CHUNK (cp)) +- return ptr; + ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), + CHUNK_AVAILABLE_SIZE (cp) - CHUNK_HDR_SZ); + } +-- +2.25.1 + + +From 4f05837ba6934c5b8bbc6738f8883890493f50b6 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Thu, 4 Feb 2021 11:52:14 +0000 +Subject: [PATCH 04/11] malloc: Avoid taggig mmaped memory on free + +Either the memory belongs to the dumped area, in which case we don't +want to tag (the dumped area has the same tag as malloc internal data +so tagging is unnecessary, but chunks there may not have the right +alignment for the tag granule), or the memory will be unmapped +immediately (and thus tagging is not useful). + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/malloc.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 61c25d0f93..ecb87350b0 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3284,9 +3284,6 @@ __libc_free (void *mem) + + p = mem2chunk (mem); + +- /* Mark the chunk as belonging to the library again. */ +- (void)TAG_REGION (chunk2rawmem (p), CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); +- + if (chunk_is_mmapped (p)) /* release mmapped memory. */ + { + /* See if the dynamic brk/mmap threshold needs adjusting. +@@ -3307,6 +3304,10 @@ __libc_free (void *mem) + { + MAYBE_INIT_TCACHE (); + ++ /* Mark the chunk as belonging to the library again. */ ++ (void)TAG_REGION (chunk2rawmem (p), ++ CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); ++ + ar_ptr = arena_for_chunk (p); + _int_free (ar_ptr, p, 0); + } +-- +2.25.1 + + +From 673fad3798846101b77a89595cfa17f334a1c898 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Tue, 16 Feb 2021 14:12:25 +0000 +Subject: [PATCH 05/11] malloc: Refactor TAG_ macros to avoid indirection + +This does not change behaviour, just removes one layer of indirection +in the internal memory tagging logic. + +Use tag_ and mtag_ prefixes instead of __tag_ and __mtag_ since these +are all symbols with internal linkage, private to malloc.c, so there +is no user namespace pollution issue. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/arena.c | 16 +++++----- + malloc/hooks.c | 10 +++--- + malloc/malloc.c | 81 +++++++++++++++++++++++-------------------------- + 3 files changed, 51 insertions(+), 56 deletions(-) + +diff --git a/malloc/arena.c b/malloc/arena.c +index 0777dc70c6..d0778fea92 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -332,12 +332,12 @@ ptmalloc_init (void) + if (__MTAG_SBRK_UNTAGGED) + __morecore = __failing_morecore; + +- __mtag_mmap_flags = __MTAG_MMAP_FLAGS; +- __tag_new_memset = __mtag_tag_new_memset; +- __tag_region = __libc_mtag_tag_region; +- __tag_new_usable = __mtag_tag_new_usable; +- __tag_at = __libc_mtag_address_get_tag; +- __mtag_granule_mask = ~(size_t)(__MTAG_GRANULE_SIZE - 1); ++ mtag_mmap_flags = __MTAG_MMAP_FLAGS; ++ tag_new_memset = __mtag_tag_new_memset; ++ tag_region = __libc_mtag_tag_region; ++ tag_new_usable = __mtag_tag_new_usable; ++ tag_at = __libc_mtag_address_get_tag; ++ mtag_granule_mask = ~(size_t)(__MTAG_GRANULE_SIZE - 1); + } + #endif + +@@ -557,7 +557,7 @@ new_heap (size_t size, size_t top_pad) + } + } + } +- if (__mprotect (p2, size, MTAG_MMAP_FLAGS | PROT_READ | PROT_WRITE) != 0) ++ if (__mprotect (p2, size, mtag_mmap_flags | PROT_READ | PROT_WRITE) != 0) + { + __munmap (p2, HEAP_MAX_SIZE); + return 0; +@@ -587,7 +587,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) ++ mtag_mmap_flags | PROT_READ | PROT_WRITE) != 0) + return -2; + + h->mprotect_size = new_size; +diff --git a/malloc/hooks.c b/malloc/hooks.c +index efec05f0a8..d8e304c31c 100644 +--- a/malloc/hooks.c ++++ b/malloc/hooks.c +@@ -68,7 +68,7 @@ __malloc_check_init (void) + 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)) ++ ((unsigned char *) tag_at (((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 +@@ -249,7 +249,7 @@ malloc_check (size_t sz, const void *caller) + 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 (tag_new_usable (victim), sz); + } + + static void +@@ -280,7 +280,7 @@ free_check (void *mem, const void *caller) + else + { + /* Mark the chunk as belonging to the library again. */ +- (void)TAG_REGION (chunk2rawmem (p), CHUNK_AVAILABLE_SIZE (p) ++ (void)tag_region (chunk2rawmem (p), CHUNK_AVAILABLE_SIZE (p) + - CHUNK_HDR_SZ); + _int_free (&main_arena, p, 1); + __libc_lock_unlock (main_arena.mutex); +@@ -375,7 +375,7 @@ invert: + + __libc_lock_unlock (main_arena.mutex); + +- return mem2mem_check (TAG_NEW_USABLE (newmem), bytes); ++ return mem2mem_check (tag_new_usable (newmem), bytes); + } + + static void * +@@ -417,7 +417,7 @@ memalign_check (size_t alignment, size_t bytes, const void *caller) + 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 (tag_new_usable (mem), bytes); + } + + #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_25) +diff --git a/malloc/malloc.c b/malloc/malloc.c +index ecb87350b0..62d00f54cc 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -413,26 +413,26 @@ void *(*__morecore)(ptrdiff_t) = __default_morecore; + operations can continue to be used. Support macros are used to do + this: + +- void *TAG_NEW_MEMSET (void *ptr, int, val, size_t size) ++ void *tag_new_memset (void *ptr, int, val, size_t size) + + Has the same interface as memset(), but additionally allocates a + new tag, colors the memory with that tag and returns a pointer that + is correctly colored for that location. The non-tagging version + will simply call memset. + +- void *TAG_REGION (void *ptr, size_t size) ++ 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) ++ 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) ++ 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 +@@ -455,25 +455,20 @@ __default_tag_nop (void *ptr) + return ptr; + } + +-static int __mtag_mmap_flags = 0; +-static size_t __mtag_granule_mask = ~(size_t)0; ++static int mtag_mmap_flags = 0; ++static size_t mtag_granule_mask = ~(size_t)0; + +-static void *(*__tag_new_memset)(void *, int, size_t) = memset; +-static void *(*__tag_region)(void *, size_t) = __default_tag_region; +-static void *(*__tag_new_usable)(void *) = __default_tag_nop; +-static void *(*__tag_at)(void *) = __default_tag_nop; ++static void *(*tag_new_memset)(void *, int, size_t) = memset; ++static void *(*tag_region)(void *, size_t) = __default_tag_region; ++static void *(*tag_new_usable)(void *) = __default_tag_nop; ++static void *(*tag_at)(void *) = __default_tag_nop; + +-# define MTAG_MMAP_FLAGS __mtag_mmap_flags +-# define TAG_NEW_MEMSET(ptr, val, size) __tag_new_memset (ptr, val, size) +-# define TAG_REGION(ptr, size) __tag_region (ptr, size) +-# define TAG_NEW_USABLE(ptr) __tag_new_usable (ptr) +-# define TAG_AT(ptr) __tag_at (ptr) + #else +-# define MTAG_MMAP_FLAGS 0 +-# define TAG_NEW_MEMSET(ptr, val, size) memset (ptr, val, size) +-# define TAG_REGION(ptr, size) (ptr) +-# define TAG_NEW_USABLE(ptr) (ptr) +-# define TAG_AT(ptr) (ptr) ++# define mtag_mmap_flags 0 ++# define tag_new_memset(ptr, val, size) memset (ptr, val, size) ++# define tag_region(ptr, size) (ptr) ++# define tag_new_usable(ptr) (ptr) ++# define tag_at(ptr) (ptr) + #endif + + #include <string.h> +@@ -1305,8 +1300,8 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + /* Convert between user mem pointers and chunk pointers, updating any + memory tags on the pointer to respect the tag value at that + location. */ +-#define chunk2mem(p) ((void*)TAG_AT (((char*)(p) + CHUNK_HDR_SZ))) +-#define mem2chunk(mem) ((mchunkptr)TAG_AT (((char*)(mem) - CHUNK_HDR_SZ))) ++#define chunk2mem(p) ((void *)tag_at (((char*)(p) + CHUNK_HDR_SZ))) ++#define mem2chunk(mem) ((mchunkptr)tag_at (((char*)(mem) - CHUNK_HDR_SZ))) + + /* The smallest possible chunk */ + #define MIN_CHUNK_SIZE (offsetof(struct malloc_chunk, fd_nextsize)) +@@ -1337,7 +1332,7 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + #ifdef USE_MTAG + #define CHUNK_AVAILABLE_SIZE(p) \ + ((chunksize (p) + (chunk_is_mmapped (p) ? 0 : SIZE_SZ)) \ +- & __mtag_granule_mask) ++ & mtag_granule_mask) + #else + #define CHUNK_AVAILABLE_SIZE(p) \ + (chunksize (p) + (chunk_is_mmapped (p) ? 0 : SIZE_SZ)) +@@ -1361,7 +1356,7 @@ checked_request2size (size_t req, size_t *sz) __nonnull (1) + 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. */ +- req = (req + ~__mtag_granule_mask) & __mtag_granule_mask; ++ req = (req + ~mtag_granule_mask) & mtag_granule_mask; + #endif + + *sz = request2size (req); +@@ -2467,7 +2462,7 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + if ((unsigned long) (size) > (unsigned long) (nb)) + { + mm = (char *) (MMAP (0, size, +- MTAG_MMAP_FLAGS | PROT_READ | PROT_WRITE, 0)); ++ mtag_mmap_flags | PROT_READ | PROT_WRITE, 0)); + + if (mm != MAP_FAILED) + { +@@ -2665,7 +2660,7 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av) + if ((unsigned long) (size) > (unsigned long) (nb)) + { + char *mbrk = (char *) (MMAP (0, size, +- MTAG_MMAP_FLAGS | PROT_READ | PROT_WRITE, ++ mtag_mmap_flags | PROT_READ | PROT_WRITE, + 0)); + + if (mbrk != MAP_FAILED) +@@ -3221,14 +3216,14 @@ __libc_malloc (size_t bytes) + && tcache->counts[tc_idx] > 0) + { + victim = tcache_get (tc_idx); +- return TAG_NEW_USABLE (victim); ++ return tag_new_usable (victim); + } + DIAG_POP_NEEDS_COMMENT; + #endif + + if (SINGLE_THREAD_P) + { +- victim = TAG_NEW_USABLE (_int_malloc (&main_arena, bytes)); ++ victim = tag_new_usable (_int_malloc (&main_arena, bytes)); + assert (!victim || chunk_is_mmapped (mem2chunk (victim)) || + &main_arena == arena_for_chunk (mem2chunk (victim))); + return victim; +@@ -3249,7 +3244,7 @@ __libc_malloc (size_t bytes) + if (ar_ptr != NULL) + __libc_lock_unlock (ar_ptr->mutex); + +- victim = TAG_NEW_USABLE (victim); ++ victim = tag_new_usable (victim); + + assert (!victim || chunk_is_mmapped (mem2chunk (victim)) || + ar_ptr == arena_for_chunk (mem2chunk (victim))); +@@ -3305,7 +3300,7 @@ __libc_free (void *mem) + MAYBE_INIT_TCACHE (); + + /* Mark the chunk as belonging to the library again. */ +- (void)TAG_REGION (chunk2rawmem (p), ++ (void)tag_region (chunk2rawmem (p), + CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); + + ar_ptr = arena_for_chunk (p); +@@ -3408,7 +3403,7 @@ __libc_realloc (void *oldmem, size_t bytes) + 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 tag_new_usable (newmem); + } + #endif + /* Note the extra SIZE_SZ overhead. */ +@@ -3451,7 +3446,7 @@ __libc_realloc (void *oldmem, size_t bytes) + { + size_t sz = CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ; + memcpy (newp, oldmem, sz); +- (void) TAG_REGION (chunk2rawmem (oldp), sz); ++ (void) tag_region (chunk2rawmem (oldp), sz); + _int_free (ar_ptr, oldp, 0); + } + } +@@ -3509,7 +3504,7 @@ _mid_memalign (size_t alignment, size_t bytes, void *address) + 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 tag_new_usable (p); + } + + arena_get (ar_ptr, bytes + alignment + MINSIZE); +@@ -3527,7 +3522,7 @@ _mid_memalign (size_t alignment, size_t bytes, void *address) + + assert (!p || chunk_is_mmapped (mem2chunk (p)) || + ar_ptr == arena_for_chunk (mem2chunk (p))); +- return TAG_NEW_USABLE (p); ++ return tag_new_usable (p); + } + /* For ISO C11. */ + weak_alias (__libc_memalign, aligned_alloc) +@@ -3544,7 +3539,7 @@ __libc_valloc (size_t bytes) + void *address = RETURN_ADDRESS (0); + size_t pagesize = GLRO (dl_pagesize); + p = _mid_memalign (pagesize, bytes, address); +- return TAG_NEW_USABLE (p); ++ return tag_new_usable (p); + } + + void * +@@ -3569,7 +3564,7 @@ __libc_pvalloc (size_t bytes) + rounded_bytes = rounded_bytes & -(pagesize - 1); + + p = _mid_memalign (pagesize, rounded_bytes, address); +- return TAG_NEW_USABLE (p); ++ return tag_new_usable (p); + } + + void * +@@ -3666,7 +3661,7 @@ __libc_calloc (size_t n, size_t elem_size) + regardless of MORECORE_CLEARS, so we zero the whole block while + doing so. */ + #ifdef USE_MTAG +- return TAG_NEW_MEMSET (mem, 0, CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); ++ return tag_new_memset (mem, 0, CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); + #else + INTERNAL_SIZE_T csz = chunksize (p); + +@@ -4821,7 +4816,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 (chunk2rawmem (oldp)); ++ return tag_new_usable (chunk2rawmem (oldp)); + } + + /* Try to expand forward into next chunk; split off remainder below */ +@@ -4856,8 +4851,8 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + { + void *oldmem = chunk2rawmem (oldp); + size_t sz = CHUNK_AVAILABLE_SIZE (oldp) - CHUNK_HDR_SZ; +- (void) TAG_REGION (oldmem, sz); +- newmem = TAG_NEW_USABLE (newmem); ++ (void) tag_region (oldmem, sz); ++ newmem = tag_new_usable (newmem); + memcpy (newmem, oldmem, sz); + _int_free (av, oldp, 1); + check_inuse_chunk (av, newp); +@@ -4881,7 +4876,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + { + remainder = chunk_at_offset (newp, nb); + /* Clear any user-space tags before writing the header. */ +- remainder = TAG_REGION (remainder, remainder_size); ++ 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)); +@@ -4891,7 +4886,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + } + + check_inuse_chunk (av, newp); +- return TAG_NEW_USABLE (chunk2rawmem (newp)); ++ return tag_new_usable (chunk2rawmem (newp)); + } + + /* +@@ -5108,7 +5103,7 @@ musable (void *mem) + /* The usable space may be reduced if memory tagging is needed, + since we cannot share the user-space data with malloc's internal + data structure. */ +- result &= __mtag_granule_mask; ++ result &= mtag_granule_mask; + #endif + return result; + } +-- +2.25.1 + + +From f0ea41e819f40aacedf25431bedd95da9c5db534 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 27 Jan 2021 15:45:43 +0000 +Subject: [PATCH 06/11] malloc: Use global flag instead of function pointer + dispatch for mtag + +A flag check can be faster than function pointers because of how +branch prediction and speculation works and it can also remove a layer +of indirection when there is a mismatch between the malloc internal +tag_* api and __libc_mtag_* target hooks. + +Memory tagging wrapper functions are moved to malloc.c from arena.c and +the logic now checks mmap_enabled. The definition of tag_new_usable is +moved after chunk related definitions. + +This refactoring also allows using mtag_enabled checks instead of +USE_MTAG ifdefs when memory tagging support only changes code logic +when memory tagging is enabled at runtime. Note: an "if (false)" code +block is optimized away even at -O0 by gcc. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/arena.c | 33 +--------------------------- + malloc/malloc.c | 58 ++++++++++++++++++++++++++++++++----------------- + 2 files changed, 39 insertions(+), 52 deletions(-) + +diff --git a/malloc/arena.c b/malloc/arena.c +index d0778fea92..1e83bb66bd 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -287,34 +287,6 @@ extern struct dl_open_hook *_dl_open_hook; + libc_hidden_proto (_dl_open_hook); + #endif + +-#ifdef USE_MTAG +- +-/* Generate a new (random) tag value for PTR and tag the memory it +- points to upto the end of the usable size for the chunk containing +- it. Return the newly tagged pointer. */ +-static void * +-__mtag_tag_new_usable (void *ptr) +-{ +- if (ptr) +- { +- mchunkptr cp = mem2chunk(ptr); +- ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), +- CHUNK_AVAILABLE_SIZE (cp) - CHUNK_HDR_SZ); +- } +- return ptr; +-} +- +-/* Generate a new (random) tag value for PTR, set the tags for the +- memory to the new tag and initialize the memory contents to VAL. +- In practice this function will only be called with VAL=0, but we +- keep this parameter to maintain the same prototype as memset. */ +-static void * +-__mtag_tag_new_memset (void *ptr, int val, size_t size) +-{ +- return __libc_mtag_memset_with_tag (__libc_mtag_new_tag (ptr), val, size); +-} +-#endif +- + static void + ptmalloc_init (void) + { +@@ -332,11 +304,8 @@ ptmalloc_init (void) + if (__MTAG_SBRK_UNTAGGED) + __morecore = __failing_morecore; + ++ mtag_enabled = true; + mtag_mmap_flags = __MTAG_MMAP_FLAGS; +- tag_new_memset = __mtag_tag_new_memset; +- tag_region = __libc_mtag_tag_region; +- tag_new_usable = __mtag_tag_new_usable; +- tag_at = __libc_mtag_address_get_tag; + mtag_granule_mask = ~(size_t)(__MTAG_GRANULE_SIZE - 1); + } + #endif +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 62d00f54cc..253a919ec5 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -441,35 +441,41 @@ void *(*__morecore)(ptrdiff_t) = __default_morecore; + */ + + #ifdef USE_MTAG ++static bool mtag_enabled = false; ++static int mtag_mmap_flags = 0; ++static size_t mtag_granule_mask = ~(size_t)0; ++#else ++# define mtag_enabled false ++# define mtag_mmap_flags 0 ++#endif + +-/* Default implementaions when memory tagging is supported, but disabled. */ +-static void * +-__default_tag_region (void *ptr, size_t size) ++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 void * +-__default_tag_nop (void *ptr) ++static __always_inline void * ++tag_new_memset (void *ptr, int val, size_t size) + { +- return ptr; ++ if (__glibc_unlikely (mtag_enabled)) ++ return __libc_mtag_memset_with_tag (__libc_mtag_new_tag (ptr), val, size); ++ return memset (ptr, val, size); + } + +-static int mtag_mmap_flags = 0; +-static size_t mtag_granule_mask = ~(size_t)0; +- +-static void *(*tag_new_memset)(void *, int, size_t) = memset; +-static void *(*tag_region)(void *, size_t) = __default_tag_region; +-static void *(*tag_new_usable)(void *) = __default_tag_nop; +-static void *(*tag_at)(void *) = __default_tag_nop; ++/* Defined later. */ ++static void * ++tag_new_usable (void *ptr); + +-#else +-# define mtag_mmap_flags 0 +-# define tag_new_memset(ptr, val, size) memset (ptr, val, size) +-# define tag_region(ptr, size) (ptr) +-# define tag_new_usable(ptr) (ptr) +-# define tag_at(ptr) (ptr) +-#endif ++static __always_inline void * ++tag_at (void *ptr) ++{ ++ if (__glibc_unlikely (mtag_enabled)) ++ return __libc_mtag_address_get_tag (ptr); ++ return ptr; ++} + + #include <string.h> + +@@ -1460,6 +1466,18 @@ checked_request2size (size_t req, size_t *sz) __nonnull (1) + #pragma GCC poison mchunk_size + #pragma GCC poison mchunk_prev_size + ++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), ++ CHUNK_AVAILABLE_SIZE (cp) - CHUNK_HDR_SZ); ++ } ++ return ptr; ++} ++ + /* + -------------------- Internal data structures -------------------- + +-- +2.25.1 + + +From 8597244d5c3edbd672b285eea5f6dea833256f9d Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 17 Feb 2021 10:39:37 +0000 +Subject: [PATCH 07/11] malloc: Ensure the generic mtag hooks are not used + +Use inline functions instead of macros, because macros can cause unused +variable warnings and type conversion issues. We assume these functions +may appear in the code but only in dead code paths (hidden by a runtime +check), so it's important that they can compile with correct types, but +if they are actually used that should be an error. + +Currently the hooks are only used when USE_MTAG is true which only +happens on aarch64 and then the aarch64 specific code is used not this +generic header. However followup refactoring will allow the hooks to +be used with !USE_MTAG. + +Note: the const qualifier in the comment was wrong: changing tags is a +write operation. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + sysdeps/generic/libc-mtag.h | 41 ++++++++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 10 deletions(-) + +diff --git a/sysdeps/generic/libc-mtag.h b/sysdeps/generic/libc-mtag.h +index 1a866cdc0c..e8fc236b6c 100644 +--- a/sysdeps/generic/libc-mtag.h ++++ b/sysdeps/generic/libc-mtag.h +@@ -31,22 +31,43 @@ + /* 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. +- void *__libc_mtag_tag_region (const void *, size_t) */ +-#define __libc_mtag_tag_region(p, s) (p) ++ 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. */ +-#define __libc_mtag_memset_with_tag memset ++static inline void * ++__libc_mtag_memset_with_tag (void *p, int c, size_t n) ++{ ++ __libc_mtag_link_error (); ++ return memset (p, c, n); ++} + + /* Convert address P to a pointer that is tagged correctly for that +- location. +- void *__libc_mtag_address_get_tag (void*) */ +-#define __libc_mtag_address_get_tag(p) (p) ++ 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). +- void *__libc_mtag_new_tag (void*) */ +-#define __libc_mtag_new_tag(p) (p) ++ the memory addressed). */ ++static inline void * ++__libc_mtag_new_tag (void *p) ++{ ++ __libc_mtag_link_error (); ++ return p; ++} + + #endif /* _GENERIC_LIBC_MTAG_H */ +-- +2.25.1 + + +From 3d9e16280ad881d038aedba0b6fcbd9e78b29072 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Fri, 29 Jan 2021 17:07:28 +0000 +Subject: [PATCH 08/11] malloc: Only support zeroing and not arbitrary memset + with mtag + +The memset api is suboptimal and does not provide much benefit. Memory +tagging only needs a zeroing memset (and only for memory that's sized +and aligned to multiples of the tag granule), so change the internal +api and the target hooks accordingly. This is to simplify the +implementation of the target hook. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/malloc.c | 17 ++++++++--------- + sysdeps/aarch64/Makefile | 2 +- + ...g_memset_tag.S => __mtag_tag_zero_region.S} | 18 +++++++----------- + sysdeps/aarch64/libc-mtag.h | 4 ++-- + sysdeps/generic/libc-mtag.h | 6 +++--- + 5 files changed, 21 insertions(+), 26 deletions(-) + rename sysdeps/aarch64/{__mtag_memset_tag.S => __mtag_tag_zero_region.S} (82%) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 253a919ec5..01cf6e9325 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -413,12 +413,11 @@ void *(*__morecore)(ptrdiff_t) = __default_morecore; + operations can continue to be used. Support macros are used to do + this: + +- void *tag_new_memset (void *ptr, int, val, size_t size) ++ void *tag_new_zero_region (void *ptr, size_t size) + +- Has the same interface as memset(), but additionally allocates a +- new tag, colors the memory with that tag and returns a pointer that +- is correctly colored for that location. The non-tagging version +- will simply call memset. ++ 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) + +@@ -458,11 +457,11 @@ tag_region (void *ptr, size_t size) + } + + static __always_inline void * +-tag_new_memset (void *ptr, int val, size_t size) ++tag_new_zero_region (void *ptr, size_t size) + { + if (__glibc_unlikely (mtag_enabled)) +- return __libc_mtag_memset_with_tag (__libc_mtag_new_tag (ptr), val, size); +- return memset (ptr, val, size); ++ return __libc_mtag_tag_zero_region (__libc_mtag_new_tag (ptr), size); ++ return memset (ptr, 0, size); + } + + /* Defined later. */ +@@ -3679,7 +3678,7 @@ __libc_calloc (size_t n, size_t elem_size) + regardless of MORECORE_CLEARS, so we zero the whole block while + doing so. */ + #ifdef USE_MTAG +- return tag_new_memset (mem, 0, CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); ++ return tag_new_zero_region (mem, CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); + #else + INTERNAL_SIZE_T csz = chunksize (p); + +diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile +index d3ab37a40a..259070cfad 100644 +--- a/sysdeps/aarch64/Makefile ++++ b/sysdeps/aarch64/Makefile +@@ -41,7 +41,7 @@ endif + ifeq ($(subdir),misc) + sysdep_headers += sys/ifunc.h + sysdep_routines += __mtag_address_get_tag \ +- __mtag_memset_tag \ ++ __mtag_tag_zero_region \ + __mtag_new_tag \ + __mtag_tag_region + +diff --git a/sysdeps/aarch64/__mtag_memset_tag.S b/sysdeps/aarch64/__mtag_tag_zero_region.S +similarity index 82% +rename from sysdeps/aarch64/__mtag_memset_tag.S +rename to sysdeps/aarch64/__mtag_tag_zero_region.S +index 3c202888a4..74d398bba5 100644 +--- a/sysdeps/aarch64/__mtag_memset_tag.S ++++ b/sysdeps/aarch64/__mtag_tag_zero_region.S +@@ -20,9 +20,6 @@ + + #ifdef USE_MTAG + +-/* Use the same register names and assignments as memset. */ +-#include "memset-reg.h" +- + .arch armv8.5-a + .arch_extension memtag + +@@ -31,16 +28,15 @@ + /* FIXME: This is a minimal implementation. We could do much better than + this for large values of COUNT. */ + +-ENTRY(__libc_mtag_memset_with_tag) ++#define dstin x0 ++#define count x1 ++#define dst x2 + +- and valw, valw, 255 +- orr valw, valw, valw, lsl 8 +- orr valw, valw, valw, lsl 16 +- orr val, val, val, lsl 32 +- mov dst, dstin ++ENTRY(__libc_mtag_tag_zero_region) + ++ mov dst, dstin + L(loop): +- stgp val, val, [dst], #16 ++ stzg dst, [dst], #16 + subs count, count, 16 + bne L(loop) + #if 0 +@@ -49,5 +45,5 @@ L(loop): + ldg dstin, [dstin] // Recover the tag created (might be untagged). + #endif + ret +-END (__libc_mtag_memset_with_tag) ++END (__libc_mtag_tag_zero_region) + #endif /* USE_MTAG */ +diff --git a/sysdeps/aarch64/libc-mtag.h b/sysdeps/aarch64/libc-mtag.h +index 979cbb743e..f58402ccf9 100644 +--- a/sysdeps/aarch64/libc-mtag.h ++++ b/sysdeps/aarch64/libc-mtag.h +@@ -39,8 +39,8 @@ + void *__libc_mtag_tag_region (const void *, size_t) */ + void *__libc_mtag_tag_region (void *, size_t); + +-/* Optimized equivalent to __libc_mtag_tag_region followed by memset. */ +-void *__libc_mtag_memset_with_tag (void *, int, 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. +diff --git a/sysdeps/generic/libc-mtag.h b/sysdeps/generic/libc-mtag.h +index e8fc236b6c..4743e873f1 100644 +--- a/sysdeps/generic/libc-mtag.h ++++ b/sysdeps/generic/libc-mtag.h +@@ -44,12 +44,12 @@ __libc_mtag_tag_region (void *p, size_t n) + return p; + } + +-/* Optimized equivalent to __libc_mtag_tag_region followed by memset. */ ++/* Optimized equivalent to __libc_mtag_tag_region followed by memset to 0. */ + static inline void * +-__libc_mtag_memset_with_tag (void *p, int c, size_t n) ++__libc_mtag_tag_zero_region (void *p, size_t n) + { + __libc_mtag_link_error (); +- return memset (p, c, n); ++ return memset (p, 0, n); + } + + /* Convert address P to a pointer that is tagged correctly for that +-- +2.25.1 + + +From 4d596cb72342ba0734dc847653431e078a70edfc Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Tue, 16 Feb 2021 17:02:44 +0000 +Subject: [PATCH 09/11] malloc: Change calloc when tagging is disabled + +When glibc is built with memory tagging support (USE_MTAG) but it is not +enabled at runtime (mtag_enabled) then unconditional memset was used +even though that can be often avoided. + +This is for performance when tagging is supported but not enabled. +The extra check should have no overhead: tag_new_zero_region already +had a runtime check which the compiler can now optimize away. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/malloc.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 01cf6e9325..0b2aff3768 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3591,11 +3591,9 @@ __libc_calloc (size_t n, size_t elem_size) + mchunkptr oldtop; + INTERNAL_SIZE_T sz, oldtopsize; + void *mem; +-#ifndef USE_MTAG + unsigned long clearsize; + unsigned long nclears; + INTERNAL_SIZE_T *d; +-#endif + ptrdiff_t bytes; + + if (__glibc_unlikely (__builtin_mul_overflow (n, elem_size, &bytes))) +@@ -3674,12 +3672,13 @@ __libc_calloc (size_t n, size_t elem_size) + return 0; + + mchunkptr 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. */ +-#ifdef USE_MTAG +- return tag_new_zero_region (mem, CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); +-#else ++ if (__glibc_unlikely (mtag_enabled)) ++ return tag_new_zero_region (mem, CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ); ++ + INTERNAL_SIZE_T csz = chunksize (p); + + /* Two optional cases in which clearing not necessary */ +@@ -3733,7 +3732,6 @@ __libc_calloc (size_t n, size_t elem_size) + } + + return mem; +-#endif + } + + /* +-- +2.25.1 + + +From 287a35fba55a0a817db7af71ee966a37b7642bf0 Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Mon, 8 Feb 2021 12:39:01 +0000 +Subject: [PATCH 10/11] malloc: Use branches instead of mtag_granule_mask + +The branches may be better optimized since mtag_enabled is widely used. + +Granule size larger than a chunk header is not supported since then we +cannot have both the chunk header and user area granule aligned. To +fix that for targets with large granule, the chunk layout has to change. + +So code that attempted to handle the granule mask generally was changed. +This simplified CHUNK_AVAILABLE_SIZE and the logic in malloc_usable_size. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/arena.c | 1 - + malloc/malloc.c | 34 ++++++++++++++-------------------- + 2 files changed, 14 insertions(+), 21 deletions(-) + +diff --git a/malloc/arena.c b/malloc/arena.c +index 1e83bb66bd..9fbbb38a15 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -306,7 +306,6 @@ ptmalloc_init (void) + + mtag_enabled = true; + mtag_mmap_flags = __MTAG_MMAP_FLAGS; +- mtag_granule_mask = ~(size_t)(__MTAG_GRANULE_SIZE - 1); + } + #endif + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 0b2aff3768..849bd8e2c9 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -442,7 +442,6 @@ void *(*__morecore)(ptrdiff_t) = __default_morecore; + #ifdef USE_MTAG + static bool mtag_enabled = false; + static int mtag_mmap_flags = 0; +-static size_t mtag_granule_mask = ~(size_t)0; + #else + # define mtag_enabled false + # define mtag_mmap_flags 0 +@@ -1333,15 +1332,16 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) + + /* Available size of chunk. This is the size of the real usable data +- in the chunk, plus the chunk header. */ +-#ifdef USE_MTAG +-#define CHUNK_AVAILABLE_SIZE(p) \ +- ((chunksize (p) + (chunk_is_mmapped (p) ? 0 : SIZE_SZ)) \ +- & mtag_granule_mask) +-#else +-#define CHUNK_AVAILABLE_SIZE(p) \ +- (chunksize (p) + (chunk_is_mmapped (p) ? 0 : SIZE_SZ)) +-#endif ++ in the chunk, plus the chunk header. Note: If memory tagging is ++ enabled the layout changes to accomodate the granule size, this is ++ wasteful for small allocations so not done by default. The logic ++ does not work if chunk headers are not granule aligned. */ ++_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ, ++ "memory tagging is not supported with large granule."); ++#define CHUNK_AVAILABLE_SIZE(p) \ ++ (__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \ ++ chunksize (p) : \ ++ chunksize (p) + (chunk_is_mmapped (p) ? 0 : SIZE_SZ)) + + /* Check if REQ overflows when padded and aligned and if the resulting value + is less than PTRDIFF_T. Returns TRUE and the requested size or MINSIZE in +@@ -1353,7 +1353,6 @@ checked_request2size (size_t req, size_t *sz) __nonnull (1) + if (__glibc_unlikely (req > PTRDIFF_MAX)) + return false; + +-#ifdef USE_MTAG + /* 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 +@@ -1361,8 +1360,9 @@ checked_request2size (size_t req, size_t *sz) __nonnull (1) + 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. */ +- req = (req + ~mtag_granule_mask) & mtag_granule_mask; +-#endif ++ if (__glibc_unlikely (mtag_enabled)) ++ req = (req + (__MTAG_GRANULE_SIZE - 1)) & ++ ~(size_t)(__MTAG_GRANULE_SIZE - 1); + + *sz = request2size (req); + return true; +@@ -5112,14 +5112,8 @@ musable (void *mem) + result = chunksize (p) - CHUNK_HDR_SZ; + } + else if (inuse (p)) +- result = chunksize (p) - SIZE_SZ; ++ result = CHUNK_AVAILABLE_SIZE (p) - CHUNK_HDR_SZ; + +-#ifdef USE_MTAG +- /* The usable space may be reduced if memory tagging is needed, +- since we cannot share the user-space data with malloc's internal +- data structure. */ +- result &= mtag_granule_mask; +-#endif + return result; + } + return 0; +-- +2.25.1 + + +From 66de173bf919e601e408dc78772c6841ad6388ab Mon Sep 17 00:00:00 2001 +From: Szabolcs Nagy <szabolcs.nagy@arm.com> +Date: Wed, 17 Feb 2021 10:15:18 +0000 +Subject: [PATCH 11/11] malloc: Use mtag_enabled instead of USE_MTAG + +Use the runtime check where possible: it should not cause slow down in +the !USE_MTAG case since then mtag_enabled is constant false, but it +allows compiling the tagging logic so it's less likely to break or +diverge when developers only test the !USE_MTAG case. + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + malloc/hooks.c | 10 ++++------ + malloc/malloc.c | 10 ++++------ + 2 files changed, 8 insertions(+), 12 deletions(-) + +diff --git a/malloc/hooks.c b/malloc/hooks.c +index d8e304c31c..9474e199c3 100644 +--- a/malloc/hooks.c ++++ b/malloc/hooks.c +@@ -262,11 +262,10 @@ free_check (void *mem, const void *caller) + + int err = errno; + +-#ifdef USE_MTAG + /* Quickly check that the freed pointer matches the tag for the memory. + This gives a useful double-free detection. */ +- *(volatile char *)mem; +-#endif ++ if (__glibc_unlikely (mtag_enabled)) ++ *(volatile char *)mem; + + __libc_lock_lock (main_arena.mutex); + p = mem2chunk_check (mem, NULL); +@@ -310,11 +309,10 @@ realloc_check (void *oldmem, size_t bytes, const void *caller) + return NULL; + } + +-#ifdef USE_MTAG + /* Quickly check that the freed pointer matches the tag for the memory. + This gives a useful double-free detection. */ +- *(volatile char *)oldmem; +-#endif ++ if (__glibc_unlikely (mtag_enabled)) ++ *(volatile char *)oldmem; + + __libc_lock_lock (main_arena.mutex); + const mchunkptr oldp = mem2chunk_check (oldmem, &magic_p); +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 849bd8e2c9..36583120ce 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3286,11 +3286,10 @@ __libc_free (void *mem) + if (mem == 0) /* free(0) has no effect */ + return; + +-#ifdef USE_MTAG + /* Quickly check that the freed pointer matches the tag for the memory. + This gives a useful double-free detection. */ +- *(volatile char *)mem; +-#endif ++ if (__glibc_unlikely (mtag_enabled)) ++ *(volatile char *)mem; + + int err = errno; + +@@ -3352,11 +3351,10 @@ __libc_realloc (void *oldmem, size_t bytes) + if (oldmem == 0) + return __libc_malloc (bytes); + +-#ifdef USE_MTAG + /* Perform a quick check to ensure that the pointer's tag matches the + memory's tag. */ +- *(volatile char*) oldmem; +-#endif ++ if (__glibc_unlikely (mtag_enabled)) ++ *(volatile char*) oldmem; + + /* chunk corresponding to oldmem */ + const mchunkptr oldp = mem2chunk (oldmem); +-- +2.25.1 + diff --git a/poky/meta/recipes-core/glibc/glibc_2.33.bb b/poky/meta/recipes-core/glibc/glibc_2.33.bb index caa2e2ae1..925efe8cc 100644 --- a/poky/meta/recipes-core/glibc/glibc_2.33.bb +++ b/poky/meta/recipes-core/glibc/glibc_2.33.bb @@ -56,6 +56,7 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ file://0028-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch \ file://0029-wordsize.h-Unify-the-header-between-arm-and-aarch64.patch \ file://0030-powerpc-Do-not-ask-compiler-for-finding-arch.patch \ + file://mte-backports.patch \ " S = "${WORKDIR}/git" B = "${WORKDIR}/build-${TARGET_SYS}" @@ -91,7 +92,7 @@ EXTRA_OECONF += "${@get_libc_fpu_setting(bb, d)}" EXTRA_OECONF_append_x86 = " --enable-cet" EXTRA_OECONF_append_x86-64 = " --enable-cet" -PACKAGECONFIG ??= "nscd" +PACKAGECONFIG ??= "nscd memory-tagging" PACKAGECONFIG[nscd] = "--enable-nscd,--disable-nscd" PACKAGECONFIG[memory-tagging] = "--enable-memory-tagging,--disable-memory-tagging" diff --git a/poky/meta/recipes-core/glibc/ldconfig-native-2.12.1/add-riscv-support.patch b/poky/meta/recipes-core/glibc/ldconfig-native-2.12.1/add-riscv-support.patch new file mode 100644 index 000000000..fc41aee26 --- /dev/null +++ b/poky/meta/recipes-core/glibc/ldconfig-native-2.12.1/add-riscv-support.patch @@ -0,0 +1,79 @@ +From fd50228cc213d2d87f5e3cf1f123acb3fda9b04e Mon Sep 17 00:00:00 2001 +From: Christoph Muellner <cmuellner@linux.com> +Date: Mon, 28 Jun 2021 00:34:12 +0200 +Subject: [PATCH] ldconfig: Add RISC-V support + +ldconfig-native does not support RISC-V at the moment. +Let's pull the reqired constants from upstream and add +the required parsing code. + +Upstream-Status: Backport + +Signed-off-by: Christoph Muellner <cmuellner@linux.com> +--- + cache.c | 6 ++++++ + ldconfig.h | 2 ++ + readelflib.c | 10 ++++++++++ + 3 files changed, 18 insertions(+) + +diff --git a/cache.c b/cache.c +index c4f5411..a3b9e70 100644 +--- a/cache.c ++++ b/cache.c +@@ -125,6 +125,12 @@ print_entry (const char *lib, int flag, unsigned int osversion, + case FLAG_AARCH64_LIB64: + fputs (",AArch64", stdout); + break; ++ case FLAG_RISCV_FLOAT_ABI_SOFT: ++ fputs (",soft-float", stdout); ++ break; ++ case FLAG_RISCV_FLOAT_ABI_DOUBLE: ++ fputs (",double-float", stdout); ++ break; + case 0: + break; + default: +diff --git a/ldconfig.h b/ldconfig.h +index 6a8a750..2e5e379 100644 +--- a/ldconfig.h ++++ b/ldconfig.h +@@ -38,6 +38,8 @@ + #define FLAG_ARM_LIBHF 0x0900 + #define FLAG_AARCH64_LIB64 0x0a00 + #define FLAG_ARM_LIBSF 0x0b00 ++#define FLAG_RISCV_FLOAT_ABI_SOFT 0x0f00 ++#define FLAG_RISCV_FLOAT_ABI_DOUBLE 0x1000 + + /* Name of auxiliary cache. */ + #define _PATH_LDCONFIG_AUX_CACHE "/var/cache/ldconfig/aux-cache" +diff --git a/readelflib.c b/readelflib.c +index 9ec0a54..a01e1ce 100644 +--- a/readelflib.c ++++ b/readelflib.c +@@ -33,6 +33,10 @@ + #define EM_AARCH64 183 /* ARM AARCH64 */ + #endif + ++#ifndef EM_RISCV ++#define EM_RISCV 243 /* RISC-V */ ++#endif ++ + #undef check_ptr + #define check_ptr(ptr) \ + do \ +@@ -331,6 +335,12 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag, + /* see sysdeps/unix/sysv/linux/arm/readelflib.c */ + *flag |= FLAG_AARCH64_LIB64|FLAG_ELF_LIBC6; + break; ++ case EM_RISCV: ++ /* RISC-V libraries are always libc.so.6+. */ ++ /* NOTE: This does not correctly handle soft-float binaries */ ++ /* see sysdeps/unix/sysv/linux/riscv/readelflib.c */ ++ *flag |= FLAG_RISCV_FLOAT_ABI_DOUBLE|FLAG_ELF_LIBC6; ++ break; + default: + error(0, 0, "%s is a 64-bit ELF for unknown machine %lx\n", + file_name, (long)elf_header->e_machine); +-- +2.25.1 + diff --git a/poky/meta/recipes-core/glibc/ldconfig-native_2.12.1.bb b/poky/meta/recipes-core/glibc/ldconfig-native_2.12.1.bb index 919d11417..fd1630b73 100644 --- a/poky/meta/recipes-core/glibc/ldconfig-native_2.12.1.bb +++ b/poky/meta/recipes-core/glibc/ldconfig-native_2.12.1.bb @@ -15,6 +15,7 @@ SRC_URI = "file://ldconfig-native-2.12.1.tar.bz2 \ file://endian-ness_handling_fix.patch \ file://add-64-bit-flag-for-ELF64-entries.patch \ file://no-aux-cache.patch \ + file://add-riscv-support.patch \ " PR = "r2" |