+/**
+ * @const KHEAP_DATA_BUFFERS
+ *
+ * @brief
+ * The builtin heap for bags of pure bytes.
+ *
+ * @discussion
+ * This set of kalloc zones should contain pure bags of bytes with no pointers
+ * or length/offset fields.
+ *
+ * The zones forming the heap aren't sequestered from each other, however the
+ * entire heap lives in a different submap from any other kernel allocation.
+ *
+ * The main motivation behind this separation is due to the fact that a lot of
+ * these objects have been used by attackers to spray the heap to make it more
+ * predictable while exploiting use-after-frees or overflows.
+ *
+ * Common attributes that make these objects useful for spraying includes
+ * control of:
+ * - Data in allocation
+ * - Time of alloc and free (lifetime)
+ * - Size of allocation
+ */
+KALLOC_HEAP_DECLARE(KHEAP_DATA_BUFFERS);
+
+/**
+ * @const KHEAP_KEXT
+ *
+ * @brief
+ * The builtin heap for allocations made by kexts.
+ *
+ * @discussion
+ * This set of kalloc zones should contain allocations from kexts and the
+ * individual zones in this heap are sequestered.
+ */
+KALLOC_HEAP_DECLARE(KHEAP_KEXT);
+
+/**
+ * @const KHEAP_DEFAULT
+ *
+ * @brief
+ * The builtin default core kernel kalloc heap.
+ *
+ * @discussion
+ * This set of kalloc zones should contain other objects that don't have their
+ * own security mitigations. The individual zones are themselves sequestered.
+ */
+KALLOC_HEAP_DECLARE(KHEAP_DEFAULT);
+
+/**
+ * @const KHEAP_TEMP
+ *
+ * @brief
+ * A heap that represents allocations that are always done in "scope" of
+ * a thread.
+ *
+ * @discussion
+ * Allocations in this heap must be allocated and freed "in scope", which means:
+ * - the thread that did the allocation will be the one doing the free,
+ * - allocations will be freed by the time the thread returns to userspace.
+ *
+ * This is an alias on the @c KHEAP_DEFAULT heap with added checks.
+ */
+KALLOC_HEAP_DECLARE(KHEAP_TEMP);
+
+/*!
+ * @macro KALLOC_HEAP_DEFINE
+ *
+ * @abstract
+ * Defines a given kalloc heap view and what it points to.
+ *
+ * @discussion
+ * Kalloc heaps are views over one of the pre-defined builtin heaps
+ * (such as @c KHEAP_DATA_BUFFERS or @c KHEAP_DEFAULT). Instantiating
+ * a new one allows for accounting of allocations through this view.
+ *
+ * Kalloc heap views are initialized during the @c STARTUP_SUB_ZALLOC phase,
+ * as the last rank. If views on zones are created, these must have been
+ * created before this stage.
+ *
+ * @param var the name for the zone view.
+ * @param name a string describing the zone view.
+ * @param heap_id a @c KHEAP_ID_* constant.
+ */
+#define KALLOC_HEAP_DEFINE(var, name, heap_id) \
+ SECURITY_READ_ONLY_LATE(struct kalloc_heap) var[1] = { { \
+ .kh_name = name, \
+ .kh_heap_id = heap_id, \
+ } }; \
+ STARTUP_ARG(ZALLOC, STARTUP_RANK_LAST, kheap_startup_init, var)
+
+#define kalloc(size) \
+ kheap_alloc(KHEAP_DEFAULT, size, Z_WAITOK)
+
+#define kalloc_flags(size, flags) \
+ kheap_alloc(KHEAP_DEFAULT, size, flags)
+
+#define kalloc_tag(size, itag) \
+ kheap_alloc_tag(KHEAP_DEFAULT, size, Z_WAITOK, itag)
+
+#define kalloc_tag_bt(size, itag) \
+ kheap_alloc_tag_bt(KHEAP_DEFAULT, size, Z_WAITOK, itag)
+
+#define krealloc(elem, old_size, new_size, flags) \
+ kheap_realloc(KHEAP_DEFAULT, elem, old_size, new_size, flags)
+
+/*
+ * These versions allow specifying the kalloc heap to allocate memory
+ * from
+ */
+#define kheap_alloc(kalloc_heap, size, flags) \
+ ({ VM_ALLOC_SITE_STATIC(0, 0); \
+ kalloc_ext(kalloc_heap, size, flags, &site).addr; })
+
+#define kheap_alloc_tag(kalloc_heap, size, flags, itag) \
+ ({ VM_ALLOC_SITE_STATIC(0, (itag)); \
+ kalloc_ext(kalloc_heap, size, flags, &site).addr; })
+
+#define kheap_alloc_tag_bt(kalloc_heap, size, flags, itag) \
+ ({ VM_ALLOC_SITE_STATIC(VM_TAG_BT, (itag)); \
+ kalloc_ext(kalloc_heap, size, flags, &site).addr; })
+
+#define kheap_realloc(kalloc_heap, elem, old_size, new_size, flags) \
+ ({ VM_ALLOC_SITE_STATIC(0, 0); \
+ krealloc_ext(kalloc_heap, elem, old_size, new_size, flags, &site).addr; })
+
+extern void
+kfree(
+ void *data,
+ vm_size_t size);
+
+extern void
+kheap_free(
+ kalloc_heap_t heap,
+ void *data,
+ vm_size_t size);
+
+__abortlike
+extern void
+kheap_temp_leak_panic(thread_t self);
+
+#else /* XNU_KERNEL_PRIVATE */
+
+extern void *kalloc(vm_size_t size) __attribute__((alloc_size(1)));
+
+extern void kfree(void *data, vm_size_t size);
+
+#endif /* !XNU_KERNEL_PRIVATE */
+#pragma mark implementation details
+#if XNU_KERNEL_PRIVATE
+#pragma GCC visibility push(hidden)
+
+/* Used by kern_os_* and operator new */
+KALLOC_HEAP_DECLARE(KERN_OS_MALLOC);
+
+extern void kheap_startup_init(
+ kalloc_heap_t heap);