Loading...
tests/mte_testing.h /dev/null libmalloc-792.60.6
--- /dev/null
+++ libmalloc/libmalloc-792.60.6/tests/mte_testing.h
@@ -0,0 +1,115 @@
+#include <../src/platform.h>
+
+#if defined(__arm64__) && defined(__LP64__) && CONFIG_MTE && !MALLOC_TARGET_EXCLAVES
+#define MALLOC_MTE_TESTING_SUPPORTED 1
+#else
+#define MALLOC_MTE_TESTING_SUPPORTED 0
+#endif
+
+#if MALLOC_MTE_TESTING_SUPPORTED
+
+#include <os/base.h>
+#include <stddef.h>
+#include <_simple.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/sysctl.h>
+#include <errno.h>
+#include <darwintest.h>
+
+// Given a pointer, strip the tag from bits 56-59 and return the result
+#define PTR_STRIP_TAG(p) \
+	((__typeof__(p))(((uintptr_t)(p)) & ~((uintptr_t)0xf << 56)))
+// Given a pointer, return the logical tag stored in bits 56-59
+#define PTR_EXTRACT_TAG(p) ((unsigned int)((((uintptr_t)(p)) >> 56) & 0xf))
+// Return whether a pointer has a non-canonical tag in bits 56-59
+#define PTR_IS_TAGGED(p) (PTR_EXTRACT_TAG(p) != 0)
+// Given a pointer p, return a pointer with bits 56-59 set to t
+#define PTR_SET_TAG(p, t) (__typeof__(p))(((uintptr_t)t << 56) | ((uintptr_t)p))
+
+OS_ENUM(sec_transition_config, uint8_t,
+	SEC_TRANSITION_NONE,
+	SEC_TRANSITION_EMULATED,
+	SEC_TRANSITION_HARDWARE,
+);
+
+static inline const char **
+get_apple_array(void)
+{
+	// The kernel sets up the stack with the following memory layout
+	//   ┌────────┐
+	//   │  argc  │
+	//   ├────────┤
+	//   │  argv  │
+	//   ├────────┤
+	//   │  envp  │
+	//   ├────────┤
+	//   │  Apple │
+	//   └────────┘
+	// Each array of pointers is terminated by a NULL value; thus, in theory we
+	// should be able to find the Apple array right after the NULL pointer at
+	// the end of envp.
+	// However, libsanitizers has its own unsetenv implementation which it uses
+	// at initialization time to consume the environment variables it uses. This
+	// changes the layout by moving all environment variables "down", and thus
+	// leaving more than a single NULL pointer between envp and the Apple array.
+	// This applies to all variables used by libsanitizers, so after getting to
+	// the end of envp, we move forward until we find a non-NULL pointer.
+	extern char **environ;
+	char **p = environ;
+	while (*p != NULL) {
+		p++;
+	}
+	p++;
+	while (*p == NULL) {
+		p++;
+	}
+	return (const char **)p;
+}
+
+static int
+process_is_translated(void)
+{
+	int ret = 0;
+	size_t size = sizeof(ret);
+	if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) {
+		if (errno == ENOENT) {
+			return 0;
+		}
+		return -1;
+	}
+	return ret;
+}
+
+static inline sec_transition_config_t
+get_sec_transition_config(void)
+{
+	const char **apple = get_apple_array();
+	const char *flag = _simple_getenv(apple, "has_sec_transition");
+	if (flag) {
+		uint64_t value = (uint64_t)strtoull(flag, NULL, 0);
+		if (value == 1) {
+			if (process_is_translated() == 1) {
+				return SEC_TRANSITION_EMULATED;
+			}
+			return SEC_TRANSITION_HARDWARE;
+		}
+	}
+	return SEC_TRANSITION_NONE;
+}
+
+#define T_SKIP_REQUIRES_SEC_TRANSITION() \
+	do { \
+		if (get_sec_transition_config() == SEC_TRANSITION_NONE) { \
+			T_SKIP("Requires has_sec_transition=1"); \
+		} \
+	} while (0)
+
+#define T_SKIP_REQUIRES_SEC_TRANSITION_HARDWARE() \
+	do { \
+		if (get_sec_transition_config() != SEC_TRANSITION_HARDWARE) { \
+			T_SKIP("Requires has_sec_transition=1 on supported hardware"); \
+		} \
+	} while (0)
+
+#endif // MALLOC_MTE_TESTING_SUPPORTED