]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/kalloc.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / kern / kalloc.h
1 /*
2 * Copyright (c) 2000-2020 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
35 *
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.
41 *
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.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56
57 #ifdef KERNEL_PRIVATE
58
59 #ifndef _KERN_KALLOC_H_
60 #define _KERN_KALLOC_H_
61
62 #include <mach/machine/vm_types.h>
63 #include <mach/boolean.h>
64 #include <mach/vm_types.h>
65 #include <kern/zalloc.h>
66
67 __BEGIN_DECLS
68
69 #if XNU_KERNEL_PRIVATE
70
71 /*!
72 * @typedef kalloc_heap_t
73 *
74 * @abstract
75 * A kalloc heap view represents a sub-accounting context
76 * for a given kalloc heap.
77 */
78 typedef struct kalloc_heap {
79 struct kheap_zones *kh_zones;
80 zone_stats_t kh_stats;
81 const char *kh_name;
82 struct kalloc_heap *kh_next;
83 zone_kheap_id_t kh_heap_id;
84 } *kalloc_heap_t;
85
86 /*!
87 * @macro KALLOC_HEAP_DECLARE
88 *
89 * @abstract
90 * (optionally) declare a kalloc heap view in a header.
91 *
92 * @discussion
93 * Unlike kernel zones, new full blown heaps cannot be instantiated.
94 * However new accounting views of the base heaps can be made.
95 */
96 #define KALLOC_HEAP_DECLARE(var) \
97 extern struct kalloc_heap var[1]
98
99 /**
100 * @const KHEAP_ANY
101 *
102 * @brief
103 * A value that represents either the default or kext heap for codepaths that
104 * need to allow @c kheap_free() to either one.
105 *
106 * @discussion
107 * When the memory provenance is not known, this value can be used to free
108 * memory indiscriminately.
109 *
110 * Note: code using this constant can likely be used as a gadget to free
111 * arbitrary memory and its use is strongly discouraged.
112 */
113 #define KHEAP_ANY ((struct kalloc_heap *)NULL)
114
115 /**
116 * @const KHEAP_DATA_BUFFERS
117 *
118 * @brief
119 * The builtin heap for bags of pure bytes.
120 *
121 * @discussion
122 * This set of kalloc zones should contain pure bags of bytes with no pointers
123 * or length/offset fields.
124 *
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.
127 *
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.
131 *
132 * Common attributes that make these objects useful for spraying includes
133 * control of:
134 * - Data in allocation
135 * - Time of alloc and free (lifetime)
136 * - Size of allocation
137 */
138 KALLOC_HEAP_DECLARE(KHEAP_DATA_BUFFERS);
139
140 /**
141 * @const KHEAP_KEXT
142 *
143 * @brief
144 * The builtin heap for allocations made by kexts.
145 *
146 * @discussion
147 * This set of kalloc zones should contain allocations from kexts and the
148 * individual zones in this heap are sequestered.
149 */
150 KALLOC_HEAP_DECLARE(KHEAP_KEXT);
151
152 /**
153 * @const KHEAP_DEFAULT
154 *
155 * @brief
156 * The builtin default core kernel kalloc heap.
157 *
158 * @discussion
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.
161 */
162 KALLOC_HEAP_DECLARE(KHEAP_DEFAULT);
163
164 /**
165 * @const KHEAP_TEMP
166 *
167 * @brief
168 * A heap that represents allocations that are always done in "scope" of
169 * a thread.
170 *
171 * @discussion
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.
175 *
176 * This is an alias on the @c KHEAP_DEFAULT heap with added checks.
177 */
178 KALLOC_HEAP_DECLARE(KHEAP_TEMP);
179
180 /*!
181 * @macro KALLOC_HEAP_DEFINE
182 *
183 * @abstract
184 * Defines a given kalloc heap view and what it points to.
185 *
186 * @discussion
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.
190 *
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.
194 *
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.
198 */
199 #define KALLOC_HEAP_DEFINE(var, name, heap_id) \
200 SECURITY_READ_ONLY_LATE(struct kalloc_heap) var[1] = { { \
201 .kh_name = name, \
202 .kh_heap_id = heap_id, \
203 } }; \
204 STARTUP_ARG(ZALLOC, STARTUP_RANK_LAST, kheap_startup_init, var)
205
206 #define kalloc(size) \
207 kheap_alloc(KHEAP_DEFAULT, size, Z_WAITOK)
208
209 #define kalloc_flags(size, flags) \
210 kheap_alloc(KHEAP_DEFAULT, size, flags)
211
212 #define kalloc_tag(size, itag) \
213 kheap_alloc_tag(KHEAP_DEFAULT, size, Z_WAITOK, itag)
214
215 #define kalloc_tag_bt(size, itag) \
216 kheap_alloc_tag_bt(KHEAP_DEFAULT, size, Z_WAITOK, itag)
217
218 #define krealloc(elem, old_size, new_size, flags) \
219 kheap_realloc(KHEAP_DEFAULT, elem, old_size, new_size, flags)
220
221 /*
222 * These versions allow specifying the kalloc heap to allocate memory
223 * from
224 */
225 #define kheap_alloc(kalloc_heap, size, flags) \
226 ({ VM_ALLOC_SITE_STATIC(0, 0); \
227 kalloc_ext(kalloc_heap, size, flags, &site).addr; })
228
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; })
232
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; })
236
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; })
240
241 extern void
242 kfree(
243 void *data,
244 vm_size_t size);
245
246 extern void
247 kheap_free(
248 kalloc_heap_t heap,
249 void *data,
250 vm_size_t size);
251
252 __abortlike
253 extern void
254 kheap_temp_leak_panic(thread_t self);
255
256 #else /* XNU_KERNEL_PRIVATE */
257
258 extern void *kalloc(vm_size_t size) __attribute__((alloc_size(1)));
259
260 extern void kfree(void *data, vm_size_t size);
261
262 #endif /* !XNU_KERNEL_PRIVATE */
263 #pragma mark implementation details
264 #if XNU_KERNEL_PRIVATE
265 #pragma GCC visibility push(hidden)
266
267 /* Used by kern_os_* and operator new */
268 KALLOC_HEAP_DECLARE(KERN_OS_MALLOC);
269
270 extern void kheap_startup_init(
271 kalloc_heap_t heap);
272
273
274 /*
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.
278 */
279 struct kalloc_result {
280 void *addr;
281 vm_size_t size;
282 };
283
284 extern struct kalloc_result
285 kalloc_ext(
286 kalloc_heap_t kheap,
287 vm_size_t size,
288 zalloc_flags_t flags,
289 vm_allocation_site_t *site);
290
291 extern struct kalloc_result
292 krealloc_ext(
293 kalloc_heap_t kheap,
294 void *addr,
295 vm_size_t old_size,
296 vm_size_t new_size,
297 zalloc_flags_t flags,
298 vm_allocation_site_t *site);
299
300 extern struct kalloc_result
301 kheap_realloc_addr(
302 kalloc_heap_t kheap,
303 void *addr,
304 vm_size_t new_size,
305 zalloc_flags_t flags,
306 vm_allocation_site_t *site);
307
308
309 /* these versions update the size reference with the actual size allocated */
310
311 static inline void *
312 kallocp_ext(
313 kalloc_heap_t kheap,
314 vm_size_t *size,
315 zalloc_flags_t flags,
316 vm_allocation_site_t *site)
317 {
318 struct kalloc_result kar = kalloc_ext(kheap, *size, flags, site);
319 *size = kar.size;
320 return kar.addr;
321 }
322
323 #define kallocp(sizep) \
324 ({ VM_ALLOC_SITE_STATIC(0, 0); \
325 kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
326
327 #define kallocp_tag(sizep, itag) \
328 ({ VM_ALLOC_SITE_STATIC(0, (itag)); \
329 kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
330
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); })
334
335 extern vm_size_t
336 kalloc_size(
337 void *addr);
338
339 extern void
340 kheap_free_addr(
341 kalloc_heap_t heap,
342 void *addr);
343
344 extern vm_size_t
345 kalloc_bucket_size(
346 vm_size_t size);
347
348 /*
349 * These macros set "elem" to NULL on free.
350 *
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.
353 */
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); \
361 })
362
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); \
371 })
372
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); \
380 })
381
382 extern zone_t
383 kalloc_heap_zone_for_size(
384 kalloc_heap_t heap,
385 vm_size_t size);
386
387 extern vm_size_t kalloc_max_prerounded;
388 extern vm_size_t kalloc_large_total;
389
390 extern void
391 kern_os_kfree(
392 void *addr,
393 vm_size_t size);
394
395 #pragma GCC visibility pop
396 #endif /* XNU_KERNEL_PRIVATE */
397
398 extern void
399 kern_os_zfree(
400 zone_t zone,
401 void *addr,
402 vm_size_t size);
403
404 __END_DECLS
405
406 #endif /* _KERN_KALLOC_H_ */
407
408 #endif /* KERNEL_PRIVATE */