Skip to content

Commit 429fc73

Browse files
authored
Merge pull request #217 from struct/mte_support
Add ARM MTE Support - May be broken
2 parents 9ab4173 + cddf69f commit 429fc73

16 files changed

Lines changed: 326 additions & 28 deletions

.github/workflows/testsuite.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
runs-on: ubuntu-latest
1212
strategy:
1313
matrix:
14-
version: [11, 12, 13, 14, 15]
14+
version: [12, 13, 14, 15]
1515
steps:
1616
- uses: actions/checkout@v4
1717
- run: |

Makefile

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ ISO_DTOR_CLEANUP = -DISO_DTOR_CLEANUP=0
194194
## UAF_PTR_PAGE is enabled for better crash handling
195195
SIGNAL_HANDLER = -DSIGNAL_HANDLER=0
196196

197+
## Enable AARCH64 / ARMv8.5a Memory Tagging Extension support
198+
#ARM_MTE = -DARM_MTE=1 -march=armv8.5-a+memtag
199+
197200
## If you know your target will have an ARMv8.1-A or newer and
198201
## supports Top Byte Ignore (TBI) then you want to enable this.
199202
## (Currently unused)
@@ -280,6 +283,23 @@ LTO =
280283
HUGE_PAGES =
281284
endif
282285

286+
ifneq ($(ARM_MTE), )
287+
ifneq ($(UNAME), Linux)
288+
$(error "ARM MTE is only supported on Linux / Android")
289+
endif
290+
291+
ifneq ($(DISABLE_CANARY), -DDISABLE_CANARY=1)
292+
$(error "Disable canaries before continuing")
293+
endif
294+
295+
ifneq ($(MEMORY_TAGGING), -DMEMORY_TAGGING=0)
296+
$(error "Disable software tagging before continuing")
297+
endif
298+
299+
CC = clang-12
300+
CXX = clang++-12
301+
endif
302+
283303
HOOKS = $(MALLOC_HOOK)
284304
OPTIMIZE = -O2 -fstrict-aliasing -Wstrict-aliasing
285305
COMMON_CFLAGS = -Wall -Iinclude/ $(THREAD_SUPPORT) $(PRE_POPULATE_PAGES) $(STARTUP_MEM_USAGE)
@@ -295,7 +315,7 @@ CFLAGS += $(COMMON_CFLAGS) $(DISABLE_CANARY) $(BUILD_ERROR_FLAGS) $(HOOKS) $(HEA
295315
$(ABORT_NO_ENTROPY) $(ISO_DTOR_CLEANUP) $(RANDOMIZE_FREELIST) $(USE_SPINLOCK) $(HUGE_PAGES) $(USE_MLOCK) \
296316
$(MEMORY_TAGGING) $(STRONG_SIZE_ISOLATION) $(MEMSET_SANITY) $(AUTO_CTOR_DTOR) $(SIGNAL_HANDLER) \
297317
$(BIG_ZONE_META_DATA_GUARD) $(BIG_ZONE_GUARD) $(PROTECT_UNUSED_BIG_ZONE) $(MASK_PTRS) $(SANITIZE_CHUNKS) $(FUZZ_MODE) \
298-
$(PERM_FREE_REALLOC)
318+
$(PERM_FREE_REALLOC) $(ARM_MTE)
299319
CXXFLAGS = $(COMMON_CFLAGS) -DCPP_SUPPORT=1 -std=$(STDCXX) $(SANITIZER_SUPPORT) $(HOOKS)
300320

301321
EXE_CFLAGS = -fPIE
@@ -385,7 +405,19 @@ tests: clean library_debug_unit_tests
385405
$(CC) $(CFLAGS) $(EXE_CFLAGS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(OS_FLAGS) tests/pool_test.c $(ISO_ALLOC_PRINTF_SRC) -o $(BUILD_DIR)/pool_test $(LDFLAGS)
386406
utils/run_tests.sh
387407

408+
mte_test: clean
409+
@echo "make mte_test"
410+
$(CC) $(CFLAGS) $(C_SRCS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(EXE_CFLAGS) $(OS_FLAGS) tests/tests.c -o $(BUILD_DIR)/tests
411+
$(CC) $(CFLAGS) $(C_SRCS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(EXE_CFLAGS) $(OS_FLAGS) tests/interfaces_test.c -o $(BUILD_DIR)/interfaces_test
412+
$(CC) $(CFLAGS) $(C_SRCS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(EXE_CFLAGS) $(OS_FLAGS) tests/heap_overflow.c -o $(BUILD_DIR)/heap_overflow
413+
$(CC) $(CFLAGS) $(C_SRCS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(EXE_CFLAGS) $(OS_FLAGS) tests/double_free.c -o $(BUILD_DIR)/double_free
414+
qemu-aarch64-static -cpu max build/tests
415+
qemu-aarch64-static -cpu max build/interfaces_test
416+
qemu-aarch64-static -cpu max build/heap_overflow
417+
qemu-aarch64-static -cpu max build/double_free
418+
388419
tagging_tests: clean cpp_library_debug
420+
@echo "make tagging_tests"
389421
$(CC) $(CFLAGS) $(EXE_CFLAGS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(OS_FLAGS) tests/tagged_ptr_test.c $(ISO_ALLOC_PRINTF_SRC) -o $(BUILD_DIR)/tagged_ptr_test $(LDFLAGS)
390422
$(CC) $(CFLAGS) $(EXE_CFLAGS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(OS_FLAGS) tests/uaf_tag_ptr_test.c $(ISO_ALLOC_PRINTF_SRC) -o $(BUILD_DIR)/uaf_tag_ptr_test $(LDFLAGS)
391423
$(CC) $(CFLAGS) $(EXE_CFLAGS) $(DEBUG_LOG_FLAGS) $(GDB_FLAGS) $(OS_FLAGS) tests/bad_tag_ptr_test.c $(ISO_ALLOC_PRINTF_SRC) -o $(BUILD_DIR)/bad_tag_ptr_test $(LDFLAGS)

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ When enabled, the `CPU_PIN` feature will restrict allocations from a given zone
8686
* `PROTECT_FREE_BIG_ZONES` Marks big zones on the free list as `PROT_NONE` when not in use
8787
* `BIG_ZONE_META_DATA_GUARD` Enables guard pages for big zone meta data
8888
* `BIG_ZONE_GUARD` Enables guard pages for big zone user pages
89+
* `ARM_MTE` Enables support for the ARM v8.5a Memory Tagging Extension
8990

9091
## Building
9192

@@ -125,10 +126,12 @@ The Makefile targets are very simple:
125126

126127
## Android
127128

128-
To build Android libraries for x86_64 and ARM64 architectures just `cd` into the `android/jni` directory and run `ndk-build`.
129+
To build Android libraries for the ARM64 architecture just `cd` into the `android/jni` directory and run `ndk-build`.
129130

130131
For those of you on an M1 based Mac you can still build IsoAlloc with the following command:
131132
`arch -x86_64 /bin/bash -c $ANDROID_NDK_HOME/build/ndk-build`
133+
or
134+
`~/Library/Android/sdk/ndk/26.1.10909125/ndk-build`
132135

133136
## Linking With C++
134137

android/jni/Android.mk

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ LOCAL_CFLAGS := -DTHREAD_SUPPORT=1 -pthread \
1414
-DPROTECT_FREE_BIG_ZONES=0 -DMASK_PTRS=1 -DSIGNAL_HANDLER=0 \
1515
-DUSE_MLOCK=1 -DNO_ZERO_ALLOCATIONS=1 -DABORT_ON_NULL=0 \
1616
-DABORT_NO_ENTROPY=1 -DMEMCPY_SANITY=0 -DMEMSET_SANITY=0 \
17-
-DSTRONG_SIZE_ISOLATION=0 -DISO_DTOR_CLEANUP=0
17+
-DSTRONG_SIZE_ISOLATION=0 -DISO_DTOR_CLEANUP=0 -DARM_MTE=1 \
18+
-march=armv8.5-a+memtag
1819

1920
LOCAL_SRC_FILES := ../../src/iso_alloc.c ../../src/iso_alloc_printf.c ../../src/iso_alloc_random.c \
2021
../../src/iso_alloc_search.c ../../src/iso_alloc_interfaces.c ../../src/iso_alloc_profiler.c \
2122
../../src/iso_alloc_sanity.c ../../src/iso_alloc_util.c ../../src/malloc_hook.c \
22-
../../src/libc_hook.c ../../src/iso_alloc_mem_tags.c
23+
../../src/libc_hook.c ../../src/iso_alloc_mem_tags.c ../../src/iso_alloc_mte.c
2324

2425
LOCAL_C_INCLUDES := ../../include/
2526

android/jni/Application.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
APP_ABI := arm64-v8a x86_64
1+
APP_ABI := arm64-v8a
22
APP_PLATFORM := android-28

include/iso_alloc_ds.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ typedef struct {
152152
int32_t big_zone_free_count;
153153
int32_t big_zone_used_count;
154154
uint16_t zones_used;
155+
#if ARM_MTE
156+
bool arm_mte_enabled;
157+
#endif
155158
} __attribute__((aligned(sizeof(int64_t)))) iso_alloc_root;
156159

157160
typedef struct {

include/iso_alloc_internal.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ INTERNAL_HIDDEN iso_alloc_zone_t *find_suitable_zone(size_t size);
368368
INTERNAL_HIDDEN iso_alloc_zone_t *iso_new_zone(size_t size, bool internal);
369369
INTERNAL_HIDDEN iso_alloc_zone_t *_iso_new_zone(size_t size, bool internal, int32_t index);
370370
INTERNAL_HIDDEN iso_alloc_zone_t *iso_find_zone_bitmap_range(const void *p);
371-
INTERNAL_HIDDEN iso_alloc_zone_t *iso_find_zone_range(const void *p);
371+
INTERNAL_HIDDEN iso_alloc_zone_t *iso_find_zone_range(void *p);
372372
INTERNAL_HIDDEN iso_alloc_zone_t *search_chunk_lookup_table(const void *p);
373373
INTERNAL_HIDDEN bit_slot_t iso_scan_zone_free_slot_slow(iso_alloc_zone_t *zone);
374374
INTERNAL_HIDDEN bit_slot_t iso_scan_zone_free_slot(iso_alloc_zone_t *zone);
@@ -416,6 +416,16 @@ INTERNAL_HIDDEN int64_t check_canary_no_abort(iso_alloc_zone_t *zone, const void
416416
INTERNAL_HIDDEN void _iso_alloc_initialize(void);
417417
INTERNAL_HIDDEN void _iso_alloc_destroy(void);
418418

419+
#if ARM_MTE
420+
INLINE void *iso_mte_untag_ptr(void *p);
421+
INLINE uint8_t iso_mte_extract_tag(void *p);
422+
INLINE bool iso_is_mte_supported(void);
423+
INLINE void *iso_mte_set_tag_range(void *p, size_t size);
424+
INLINE void *iso_mte_create_tag(void *p, uint64_t exclusion_mask);
425+
INLINE void iso_mte_set_tag(void *p);
426+
INLINE void *iso_mte_get_tag(void *p);
427+
#endif
428+
419429
#if SIGNAL_HANDLER
420430
INTERNAL_HIDDEN void handle_signal(int sig, siginfo_t *si, void *ctx);
421431
#endif

include/iso_alloc_util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ INTERNAL_HIDDEN void *create_guard_page(void *p);
2525
INTERNAL_HIDDEN INLINE void darwin_reuse(void *p, size_t size);
2626
INTERNAL_HIDDEN void unmap_guarded_pages(void *p, size_t size);
2727
INTERNAL_HIDDEN ASSUME_ALIGNED void *mmap_guarded_rw_pages(size_t size, bool populate, const char *name);
28+
INTERNAL_HIDDEN ASSUME_ALIGNED void *mmap_guarded_rw_mte_pages(size_t size, bool populate, const char *name);
2829
INTERNAL_HIDDEN ASSUME_ALIGNED void *mmap_rw_pages(size_t size, bool populate, const char *name);
30+
INTERNAL_HIDDEN ASSUME_ALIGNED void *mmap_rw_mte_pages(size_t size, bool populate, const char *name);
2931
INTERNAL_HIDDEN ASSUME_ALIGNED void *mmap_pages(size_t size, bool populate, const char *name, int32_t prot);
3032
INTERNAL_HIDDEN void mprotect_pages(void *p, size_t size, int32_t protection);
3133
INTERNAL_HIDDEN int32_t name_mapping(void *p, size_t sz, const char *name);

include/os/android.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include <sys/prctl.h>
7+
#include <sys/auxv.h>
78

89
/* This magic number is usually defined by Android Bionic:
910
* https://android.googlesource.com/platform/bionic/+/263325d/libc/include/sys/prctl.h#42 */
@@ -14,3 +15,34 @@
1415
#ifndef PR_SET_VMA_ANON_NAME
1516
#define PR_SET_VMA_ANON_NAME 0
1617
#endif
18+
19+
#if (__clang_major__ >= 12 && defined(__aarch64__) && !defined(__ILP32__)) && ARM_MTE == 1
20+
/* TODO: these belong in an aarch specific header */
21+
#ifndef PROT_MTE
22+
#define PROT_MTE 0x20
23+
#endif
24+
#ifndef PR_SET_TAGGED_ADDR_CTRL
25+
#define PR_SET_TAGGED_ADDR_CTRL 54
26+
#endif
27+
#ifndef PR_GET_TAGGED_ADDR_CTRL
28+
#define PR_GET_TAGGED_ADDR_CTRL 56
29+
#endif
30+
#ifndef PR_TAGGED_ADDR_ENABLE
31+
#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
32+
#endif
33+
#ifndef PR_MTE_TCF_SHIFT
34+
#define PR_MTE_TCF_SHIFT 1
35+
#endif
36+
#ifndef PR_MTE_TAG_SHIFT
37+
#define PR_MTE_TAG_SHIFT 3
38+
#endif
39+
#ifndef PR_MTE_TCF_NONE
40+
#define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
41+
#endif
42+
#ifndef PR_MTE_TCF_SYNC
43+
#define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
44+
#endif
45+
#ifndef PR_MTE_TCF_MASK
46+
#define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
47+
#endif
48+
#endif

include/os/linux.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include <sys/prctl.h>
7+
#include <sys/auxv.h>
78
#include <byteswap.h>
89
/* Get linux kernel version */
910
#include <linux/version.h>
@@ -29,3 +30,34 @@
2930
#endif
3031

3132
#define ENVIRON environ
33+
34+
#if (__clang_major__ >= 12 && defined(__aarch64__) && !defined(__ILP32__)) && ARM_MTE == 1
35+
/* TODO: these belong in an aarch specific header */
36+
#ifndef PROT_MTE
37+
#define PROT_MTE 0x20
38+
#endif
39+
#ifndef PR_SET_TAGGED_ADDR_CTRL
40+
#define PR_SET_TAGGED_ADDR_CTRL 54
41+
#endif
42+
#ifndef PR_GET_TAGGED_ADDR_CTRL
43+
#define PR_GET_TAGGED_ADDR_CTRL 56
44+
#endif
45+
#ifndef PR_TAGGED_ADDR_ENABLE
46+
#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
47+
#endif
48+
#ifndef PR_MTE_TCF_SHIFT
49+
#define PR_MTE_TCF_SHIFT 1
50+
#endif
51+
#ifndef PR_MTE_TAG_SHIFT
52+
#define PR_MTE_TAG_SHIFT 3
53+
#endif
54+
#ifndef PR_MTE_TCF_NONE
55+
#define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
56+
#endif
57+
#ifndef PR_MTE_TCF_SYNC
58+
#define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
59+
#endif
60+
#ifndef PR_MTE_TCF_MASK
61+
#define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
62+
#endif
63+
#endif

0 commit comments

Comments
 (0)