2 * Copyright (c) 2000-2020 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
59 #ifndef _KERN_KALLOC_H_
60 #define _KERN_KALLOC_H_
62 #include <mach/machine/vm_types.h>
63 #include <mach/boolean.h>
64 #include <mach/vm_types.h>
65 #include <kern/zalloc.h>
69 #if XNU_KERNEL_PRIVATE
72 * @typedef kalloc_heap_t
75 * A kalloc heap view represents a sub-accounting context
76 * for a given kalloc heap.
78 typedef struct kalloc_heap
{
79 struct kheap_zones
*kh_zones
;
80 zone_stats_t kh_stats
;
82 struct kalloc_heap
*kh_next
;
83 zone_kheap_id_t kh_heap_id
;
87 * @macro KALLOC_HEAP_DECLARE
90 * (optionally) declare a kalloc heap view in a header.
93 * Unlike kernel zones, new full blown heaps cannot be instantiated.
94 * However new accounting views of the base heaps can be made.
96 #define KALLOC_HEAP_DECLARE(var) \
97 extern struct kalloc_heap var[1]
103 * A value that represents either the default or kext heap for codepaths that
104 * need to allow @c kheap_free() to either one.
107 * When the memory provenance is not known, this value can be used to free
108 * memory indiscriminately.
110 * Note: code using this constant can likely be used as a gadget to free
111 * arbitrary memory and its use is strongly discouraged.
113 #define KHEAP_ANY ((struct kalloc_heap *)NULL)
116 * @const KHEAP_DATA_BUFFERS
119 * The builtin heap for bags of pure bytes.
122 * This set of kalloc zones should contain pure bags of bytes with no pointers
123 * or length/offset fields.
125 * The zones forming the heap aren't sequestered from each other, however the
126 * entire heap lives in a different submap from any other kernel allocation.
128 * The main motivation behind this separation is due to the fact that a lot of
129 * these objects have been used by attackers to spray the heap to make it more
130 * predictable while exploiting use-after-frees or overflows.
132 * Common attributes that make these objects useful for spraying includes
134 * - Data in allocation
135 * - Time of alloc and free (lifetime)
136 * - Size of allocation
138 KALLOC_HEAP_DECLARE(KHEAP_DATA_BUFFERS
);
144 * The builtin heap for allocations made by kexts.
147 * This set of kalloc zones should contain allocations from kexts and the
148 * individual zones in this heap are sequestered.
150 KALLOC_HEAP_DECLARE(KHEAP_KEXT
);
153 * @const KHEAP_DEFAULT
156 * The builtin default core kernel kalloc heap.
159 * This set of kalloc zones should contain other objects that don't have their
160 * own security mitigations. The individual zones are themselves sequestered.
162 KALLOC_HEAP_DECLARE(KHEAP_DEFAULT
);
168 * A heap that represents allocations that are always done in "scope" of
172 * Allocations in this heap must be allocated and freed "in scope", which means:
173 * - the thread that did the allocation will be the one doing the free,
174 * - allocations will be freed by the time the thread returns to userspace.
176 * This is an alias on the @c KHEAP_DEFAULT heap with added checks.
178 KALLOC_HEAP_DECLARE(KHEAP_TEMP
);
181 * @macro KALLOC_HEAP_DEFINE
184 * Defines a given kalloc heap view and what it points to.
187 * Kalloc heaps are views over one of the pre-defined builtin heaps
188 * (such as @c KHEAP_DATA_BUFFERS or @c KHEAP_DEFAULT). Instantiating
189 * a new one allows for accounting of allocations through this view.
191 * Kalloc heap views are initialized during the @c STARTUP_SUB_ZALLOC phase,
192 * as the last rank. If views on zones are created, these must have been
193 * created before this stage.
195 * @param var the name for the zone view.
196 * @param name a string describing the zone view.
197 * @param heap_id a @c KHEAP_ID_* constant.
199 #define KALLOC_HEAP_DEFINE(var, name, heap_id) \
200 SECURITY_READ_ONLY_LATE(struct kalloc_heap) var[1] = { { \
202 .kh_heap_id = heap_id, \
204 STARTUP_ARG(ZALLOC, STARTUP_RANK_LAST, kheap_startup_init, var)
206 #define kalloc(size) \
207 kheap_alloc(KHEAP_DEFAULT, size, Z_WAITOK)
209 #define kalloc_flags(size, flags) \
210 kheap_alloc(KHEAP_DEFAULT, size, flags)
212 #define kalloc_tag(size, itag) \
213 kheap_alloc_tag(KHEAP_DEFAULT, size, Z_WAITOK, itag)
215 #define kalloc_tag_bt(size, itag) \
216 kheap_alloc_tag_bt(KHEAP_DEFAULT, size, Z_WAITOK, itag)
218 #define krealloc(elem, old_size, new_size, flags) \
219 kheap_realloc(KHEAP_DEFAULT, elem, old_size, new_size, flags)
222 * These versions allow specifying the kalloc heap to allocate memory
225 #define kheap_alloc(kalloc_heap, size, flags) \
226 ({ VM_ALLOC_SITE_STATIC(0, 0); \
227 kalloc_ext(kalloc_heap, size, flags, &site).addr; })
229 #define kheap_alloc_tag(kalloc_heap, size, flags, itag) \
230 ({ VM_ALLOC_SITE_STATIC(0, (itag)); \
231 kalloc_ext(kalloc_heap, size, flags, &site).addr; })
233 #define kheap_alloc_tag_bt(kalloc_heap, size, flags, itag) \
234 ({ VM_ALLOC_SITE_STATIC(VM_TAG_BT, (itag)); \
235 kalloc_ext(kalloc_heap, size, flags, &site).addr; })
237 #define kheap_realloc(kalloc_heap, elem, old_size, new_size, flags) \
238 ({ VM_ALLOC_SITE_STATIC(0, 0); \
239 krealloc_ext(kalloc_heap, elem, old_size, new_size, flags, &site).addr; })
254 kheap_temp_leak_panic(thread_t self
);
256 #else /* XNU_KERNEL_PRIVATE */
258 extern void *kalloc(vm_size_t size
) __attribute__((alloc_size(1)));
260 extern void kfree(void *data
, vm_size_t size
);
262 #endif /* !XNU_KERNEL_PRIVATE */
263 #pragma mark implementation details
264 #if XNU_KERNEL_PRIVATE
265 #pragma GCC visibility push(hidden)
267 /* Used by kern_os_* and operator new */
268 KALLOC_HEAP_DECLARE(KERN_OS_MALLOC
);
270 extern void kheap_startup_init(
275 * This type is used so that kalloc_internal has good calling conventions
276 * for callers who want to cheaply both know the allocated address
277 * and the actual size of the allocation.
279 struct kalloc_result
{
284 extern struct kalloc_result
288 zalloc_flags_t flags
,
289 vm_allocation_site_t
*site
);
291 extern struct kalloc_result
297 zalloc_flags_t flags
,
298 vm_allocation_site_t
*site
);
300 extern struct kalloc_result
305 zalloc_flags_t flags
,
306 vm_allocation_site_t
*site
);
309 /* these versions update the size reference with the actual size allocated */
315 zalloc_flags_t flags
,
316 vm_allocation_site_t
*site
)
318 struct kalloc_result kar
= kalloc_ext(kheap
, *size
, flags
, site
);
323 #define kallocp(sizep) \
324 ({ VM_ALLOC_SITE_STATIC(0, 0); \
325 kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
327 #define kallocp_tag(sizep, itag) \
328 ({ VM_ALLOC_SITE_STATIC(0, (itag)); \
329 kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
331 #define kallocp_tag_bt(sizep, itag) \
332 ({ VM_ALLOC_SITE_STATIC(VM_TAG_BT, (itag)); \
333 kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
349 * These macros set "elem" to NULL on free.
351 * Note: all values passed to k*free() might be in the element to be freed,
352 * temporaries must be taken, and the resetting to be done prior to free.
354 #define kfree(elem, size) ({ \
355 _Static_assert(sizeof(elem) == sizeof(void *), "elem isn't pointer sized"); \
356 __auto_type __kfree_eptr = &(elem); \
357 __auto_type __kfree_elem = *__kfree_eptr; \
358 __auto_type __kfree_size = (size); \
359 *__kfree_eptr = (__typeof__(__kfree_elem))NULL; \
360 (kfree)((void *)__kfree_elem, __kfree_size); \
363 #define kheap_free(heap, elem, size) ({ \
364 _Static_assert(sizeof(elem) == sizeof(void *), "elem isn't pointer sized"); \
365 __auto_type __kfree_heap = (heap); \
366 __auto_type __kfree_eptr = &(elem); \
367 __auto_type __kfree_elem = *__kfree_eptr; \
368 __auto_type __kfree_size = (size); \
369 *__kfree_eptr = (__typeof__(__kfree_elem))NULL; \
370 (kheap_free)(__kfree_heap, (void *)__kfree_elem, __kfree_size); \
373 #define kheap_free_addr(heap, elem) ({ \
374 _Static_assert(sizeof(elem) == sizeof(void *), "elem isn't pointer sized"); \
375 __auto_type __kfree_heap = (heap); \
376 __auto_type __kfree_eptr = &(elem); \
377 __auto_type __kfree_elem = *__kfree_eptr; \
378 *__kfree_eptr = (__typeof__(__kfree_elem))NULL; \
379 (kheap_free_addr)(__kfree_heap, (void *)__kfree_elem); \
383 kalloc_heap_zone_for_size(
387 extern vm_size_t kalloc_max_prerounded
;
388 extern vm_size_t kalloc_large_total
;
395 #pragma GCC visibility pop
396 #endif /* XNU_KERNEL_PRIVATE */
406 #endif /* _KERN_KALLOC_H_ */
408 #endif /* KERNEL_PRIVATE */