]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/kalloc.h
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / osfmk / kern / kalloc.h
CommitLineData
1c79356b 1/*
f427ee49 2 * Copyright (c) 2000-2020 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
0a7de745 31/*
1c79356b
A
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
0a7de745 35 *
1c79356b
A
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.
0a7de745 41 *
1c79356b
A
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.
0a7de745 45 *
1c79356b 46 * Carnegie Mellon requests users of this software to return to
0a7de745 47 *
1c79356b
A
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
0a7de745 52 *
1c79356b
A
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
1c79356b 56
0a7de745 57#ifdef KERNEL_PRIVATE
91447636 58
0a7de745 59#ifndef _KERN_KALLOC_H_
1c79356b
A
60#define _KERN_KALLOC_H_
61
1c79356b 62#include <mach/machine/vm_types.h>
3e170ce0 63#include <mach/boolean.h>
3e170ce0 64#include <mach/vm_types.h>
f427ee49 65#include <kern/zalloc.h>
1c79356b 66
91447636 67__BEGIN_DECLS
1c79356b 68
3e170ce0
A
69#if XNU_KERNEL_PRIVATE
70
f427ee49
A
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 */
78typedef 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]
3e170ce0 98
f427ee49
A
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)
39037602 114
f427ee49
A
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 */
138KALLOC_HEAP_DECLARE(KHEAP_DATA_BUFFERS);
39037602 139
f427ee49
A
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 */
150KALLOC_HEAP_DECLARE(KHEAP_KEXT);
39037602 151
f427ee49
A
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 */
162KALLOC_HEAP_DECLARE(KHEAP_DEFAULT);
3e170ce0 163
f427ee49
A
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 */
178KALLOC_HEAP_DECLARE(KHEAP_TEMP);
3e170ce0 179
f427ee49
A
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)
3e170ce0 205
f427ee49
A
206#define kalloc(size) \
207 kheap_alloc(KHEAP_DEFAULT, size, Z_WAITOK)
39037602 208
f427ee49
A
209#define kalloc_flags(size, flags) \
210 kheap_alloc(KHEAP_DEFAULT, size, flags)
3e170ce0 211
f427ee49
A
212#define kalloc_tag(size, itag) \
213 kheap_alloc_tag(KHEAP_DEFAULT, size, Z_WAITOK, itag)
39037602 214
f427ee49
A
215#define kalloc_tag_bt(size, itag) \
216 kheap_alloc_tag_bt(KHEAP_DEFAULT, size, Z_WAITOK, itag)
39037602 217
f427ee49
A
218#define krealloc(elem, old_size, new_size, flags) \
219 kheap_realloc(KHEAP_DEFAULT, elem, old_size, new_size, flags)
39037602 220
f427ee49
A
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; })
39037602 228
f427ee49
A
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; })
39037602 232
f427ee49
A
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; })
39037602 236
f427ee49
A
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; })
39037602 240
f427ee49
A
241extern void
242kfree(
243 void *data,
244 vm_size_t size);
3e170ce0 245
f427ee49
A
246extern void
247kheap_free(
248 kalloc_heap_t heap,
249 void *data,
250 vm_size_t size);
3e170ce0 251
f427ee49
A
252__abortlike
253extern void
254kheap_temp_leak_panic(thread_t self);
1c79356b 255
f427ee49
A
256#else /* XNU_KERNEL_PRIVATE */
257
258extern void *kalloc(vm_size_t size) __attribute__((alloc_size(1)));
1c79356b 259
f427ee49 260extern void kfree(void *data, vm_size_t size);
9bccf70c 261
3e170ce0 262#endif /* !XNU_KERNEL_PRIVATE */
f427ee49
A
263#pragma mark implementation details
264#if XNU_KERNEL_PRIVATE
265#pragma GCC visibility push(hidden)
3e170ce0 266
f427ee49
A
267/* Used by kern_os_* and operator new */
268KALLOC_HEAP_DECLARE(KERN_OS_MALLOC);
269
270extern void kheap_startup_init(
271 kalloc_heap_t heap);
9bccf70c 272
1c79356b 273
f427ee49
A
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 */
279struct kalloc_result {
280 void *addr;
281 vm_size_t size;
282};
283
284extern struct kalloc_result
285kalloc_ext(
286 kalloc_heap_t kheap,
287 vm_size_t size,
288 zalloc_flags_t flags,
289 vm_allocation_site_t *site);
290
291extern struct kalloc_result
292krealloc_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
300extern struct kalloc_result
301kheap_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);
1c79356b 307
6d2010ae 308
f427ee49
A
309/* these versions update the size reference with the actual size allocated */
310
311static inline void *
312kallocp_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
335extern vm_size_t
336kalloc_size(
337 void *addr);
338
339extern void
340kheap_free_addr(
341 kalloc_heap_t heap,
342 void *addr);
343
344extern vm_size_t
345kalloc_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
382extern zone_t
383kalloc_heap_zone_for_size(
384 kalloc_heap_t heap,
385 vm_size_t size);
1c79356b 386
91447636 387extern vm_size_t kalloc_max_prerounded;
b0d623f7 388extern vm_size_t kalloc_large_total;
1c79356b 389
f427ee49
A
390extern void
391kern_os_kfree(
392 void *addr,
393 vm_size_t size);
394
395#pragma GCC visibility pop
396#endif /* XNU_KERNEL_PRIVATE */
397
398extern void
399kern_os_zfree(
400 zone_t zone,
401 void *addr,
402 vm_size_t size);
403
404__END_DECLS
9bccf70c 405
0a7de745 406#endif /* _KERN_KALLOC_H_ */
91447636 407
0a7de745 408#endif /* KERNEL_PRIVATE */