Loading...
--- libmalloc/libmalloc-792.1.1/src/instrumentation.c
+++ libmalloc/libmalloc-792.80.2/src/instrumentation.c
@@ -0,0 +1,116 @@
+// We need to include "internal.h" (which includes platform.h)
+// before we can use CONFIG_MTE.
+#include "internal.h"
+
+#if CONFIG_MTE
+
+MALLOC_NOEXPORT
+uint8_t *
+memtag_assign_tag(uint8_t *address, size_t size)
+{
+ // Exclude the canonical tag by default.
+ uint64_t mask = 0x0001;
+
+ // Exclude the tag currently associated with the given block.
+ mask = _memtag_exclude_tag(address, mask);
+
+ // Exclude the tag associated with the previous block.
+ // Keep the check within the page boundary, to avoid hitting potentially
+ // unmapped memory.
+ if (memtag_p2align(address, PAGE_SIZE) == memtag_p2align(address - 16, PAGE_SIZE)) {
+ mask = _memtag_exclude_tag(address - 16, mask);
+ }
+
+ // Exclude the tag associated with the next block.
+ if (memtag_p2align(address + size - 1, PAGE_SIZE) == memtag_p2align(address + size, PAGE_SIZE)) {
+ mask = _memtag_exclude_tag(address + size, mask);
+ }
+
+ return _memtag_create_random_tag(address, mask);
+}
+
+MALLOC_NOEXPORT
+uint8_t *
+memtag_init_chunk(uint8_t *chunk_start, size_t chunk_size, uint64_t block_size)
+{
+ size_t num_blocks = chunk_size / block_size;
+ uint8_t *tagged_addr = NULL;
+ uint8_t *first_block = NULL;
+ for (size_t idx = 0; idx < num_blocks; idx++) {
+ uint8_t *block_addr = &chunk_start[idx * block_size];
+ // Exclude the canonical tag by default.
+ uint64_t exclude_mask = 0x0001;
+ // Exclude the tag of the previously tagged block
+ if (tagged_addr != NULL) {
+ exclude_mask = _memtag_update_mask(tagged_addr, exclude_mask);
+ }
+ tagged_addr = _memtag_create_random_tag(block_addr, exclude_mask);
+ if (idx == 0) {
+ first_block = tagged_addr;
+ }
+ memtag_set_tag(tagged_addr, block_size);
+ }
+ return first_block;
+}
+
+#ifndef DARWINTEST
+
+bool
+memtag_handle_mismatch(void *ptr)
+{
+#if !MALLOC_TARGET_EXCLAVES
+ // Speculatively set the crash log message: this is required to inform the
+ // client in case we crash while trying to load the tag (ldg) for the
+ // pointer we were given, which might be a totally invalid value.
+ // Note that the exception generated in this case is not an MTE violation.
+ _os_set_crash_log_cause_and_message((uintptr_t)ptr,
+ "BUG IN CLIENT OF LIBMALLOC: pointer being freed was not valid");
+#endif
+
+ // Load the physical tag for the pointer.
+ const uint8_t *__unsafe_indexable ldg = memtag_fixup_ptr(ptr);
+ if (!memtag_tags_match(ptr, ldg)) {
+ // Extract the 4-bit tags, both for the logical and the physical tag.
+ // Then, compute an 8-bit value encoding the expected logical tag in the
+ // higher bits, and the physical tag in the lower bits.
+ // This value is then used as the crash report reason.
+ const uintptr_t ltag = ((uintptr_t)ptr) >> 56 & 0xf;
+ const uintptr_t ptag = ((uintptr_t)ldg) >> 56 & 0xf;
+ const uint8_t encoded = (ltag << 4) | ptag;
+
+#if !MALLOC_TARGET_EXCLAVES
+ _os_set_crash_log_cause_and_message(encoded,
+ "BUG IN CLIENT OF LIBMALLOC: MTE tag mismatch"
+ " (probable double-free)");
+ // Dereference the pointer carrying the invalid tag.
+ *(volatile char *)ptr;
+
+ // If we survived that, we must be in soft mode.
+
+ _os_set_crash_log_cause_and_message(encoded,
+ "BUG IN CLIENT OF LIBMALLOC: ignored previous invalid free"
+ " due to MTE tag mismatch in soft mode (probable double-free)");
+
+ // We'll now retry the free() with the correct tag: if there's anything
+ // else wrong other than the tag that will result in a normal abort, and
+ // if there isn't then the block will have been free()d and we'll signal
+ // to the caller to continue.
+ find_zone_and_free((void *)ldg, false);
+ return true;
+#else // !MALLOC_TARGET_EXCLAVES
+ // For Exclaves, we currently do not have an equivalent way of setting
+ // a crash log message as _os_set_crash_log_cause_and_message. Since
+ // the different context is less susceptible to inadvertently turning
+ // fatal exceptions into catchable ones, for the moment we simply abort.
+ __liblibc_fatal_error(
+ "BUG IN CLIENT OF LIBMALLOC (%llu): MTE tag mismatch",
+ (uint64_t)encoded);
+#endif // !MALLOC_TARGET_EXCLAVES
+ }
+
+ return false;
+}
+
+#endif // DARWINTEST
+
+#endif // CONFIG_MTE