xref: /xnu-10002.1.13/osfmk/kern/kalloc.h (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a)
1 /*
2  * Copyright (c) 2000-2021 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  [email protected]
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 #include <libkern/section_keywords.h>
67 #include <os/alloc_util.h>
68 #if XNU_KERNEL_PRIVATE
69 #include <kern/counter.h>
70 #endif /* XNU_KERNEL_PRIVATE */
71 
72 __BEGIN_DECLS __ASSUME_PTR_ABI_SINGLE_BEGIN
73 
74 /*!
75  * @const KALLOC_SAFE_ALLOC_SIZE
76  *
77  * @brief
78  * The maximum allocation size that is safe to allocate with Z_NOFAIL in kalloc.
79  */
80 #define KALLOC_SAFE_ALLOC_SIZE  (16u * 1024u)
81 
82 #if XNU_KERNEL_PRIVATE
83 /*!
84  * @typedef kalloc_heap_t
85  *
86  * @abstract
87  * A kalloc heap view represents a sub-accounting context
88  * for a given kalloc heap.
89  */
90 typedef struct kalloc_heap {
91 	zone_stats_t        kh_stats;
92 	const char         *__unsafe_indexable kh_name;
93 	zone_kheap_id_t     kh_heap_id;
94 	vm_tag_t            kh_tag;
95 	uint16_t            kh_type_hash;
96 	zone_id_t           kh_zstart;
97 	struct kalloc_heap *kh_views;
98 } *kalloc_heap_t;
99 
100 /*!
101  * @macro KALLOC_HEAP_DECLARE
102  *
103  * @abstract
104  * (optionally) declare a kalloc heap view in a header.
105  *
106  * @discussion
107  * Unlike kernel zones, new full blown heaps cannot be instantiated.
108  * However new accounting views of the base heaps can be made.
109  */
110 #define KALLOC_HEAP_DECLARE(var) \
111 	extern struct kalloc_heap var[1]
112 
113 /**
114  * @const KHEAP_DATA_BUFFERS
115  *
116  * @brief
117  * The builtin heap for bags of pure bytes.
118  *
119  * @discussion
120  * This set of kalloc zones should contain pure bags of bytes with no pointers
121  * or length/offset fields.
122  *
123  * The zones forming the heap aren't sequestered from each other, however the
124  * entire heap lives in a different submap from any other kernel allocation.
125  *
126  * The main motivation behind this separation is due to the fact that a lot of
127  * these objects have been used by attackers to spray the heap to make it more
128  * predictable while exploiting use-after-frees or overflows.
129  *
130  * Common attributes that make these objects useful for spraying includes
131  * control of:
132  * - Data in allocation
133  * - Time of alloc and free (lifetime)
134  * - Size of allocation
135  */
136 KALLOC_HEAP_DECLARE(KHEAP_DATA_BUFFERS);
137 
138 /**
139  * @const KHEAP_DEFAULT
140  *
141  * @brief
142  * The builtin default core kernel kalloc heap.
143  *
144  * @discussion
145  * This set of kalloc zones should contain other objects that don't have their
146  * own security mitigations. The individual zones are themselves sequestered.
147  */
148 KALLOC_HEAP_DECLARE(KHEAP_DEFAULT);
149 
150 /**
151  * @const KHEAP_KT_VAR
152  *
153  * @brief
154  * Temporary heap for variable sized kalloc type allocations
155  *
156  * @discussion
157  * This heap will be removed when logic for kalloc_type_var_views is added
158  *
159  */
160 KALLOC_HEAP_DECLARE(KHEAP_KT_VAR);
161 
162 /*!
163  * @macro KALLOC_HEAP_DEFINE
164  *
165  * @abstract
166  * Defines a given kalloc heap view and what it points to.
167  *
168  * @discussion
169  * Kalloc heaps are views over one of the pre-defined builtin heaps
170  * (such as @c KHEAP_DATA_BUFFERS or @c KHEAP_DEFAULT). Instantiating
171  * a new one allows for accounting of allocations through this view.
172  *
173  * Kalloc heap views are initialized during the @c STARTUP_SUB_ZALLOC phase,
174  * as the last rank. If views on zones are created, these must have been
175  * created before this stage.
176  *
177  * @param var           the name for the zone view.
178  * @param name          a string describing the zone view.
179  * @param heap_id       a @c KHEAP_ID_* constant.
180  */
181 #define KALLOC_HEAP_DEFINE(var, name, heap_id) \
182 	SECURITY_READ_ONLY_LATE(struct kalloc_heap) var[1] = { { \
183 	    .kh_name = (name), \
184 	    .kh_heap_id = (heap_id), \
185 	} }; \
186 	STARTUP_ARG(ZALLOC, STARTUP_RANK_MIDDLE, kheap_startup_init, var)
187 
188 
189 /*
190  * Allocations of type SO_NAME are known to not have pointers for
191  * most platforms -- for macOS this is not guaranteed
192  */
193 #if XNU_TARGET_OS_OSX
194 #define KHEAP_SONAME KHEAP_DEFAULT
195 #else /* XNU_TARGET_OS_OSX */
196 #define KHEAP_SONAME KHEAP_DATA_BUFFERS
197 #endif /* XNU_TARGET_OS_OSX */
198 
199 #endif /* XNU_KERNEL_PRIVATE */
200 
201 /*!
202  * @enum kalloc_type_flags_t
203  *
204  * @brief
205  * Flags that can be passed to @c KALLOC_TYPE_DEFINE
206  *
207  * @discussion
208  * These flags can be used to request for a specific accounting
209  * behavior.
210  *
211  * @const KT_DEFAULT
212  * Passing this flag will provide default accounting behavior
213  * i.e shared accounting unless toggled with KT_OPTIONS_ACCT is
214  * set in kt boot-arg.
215  *
216  * @const KT_PRIV_ACCT
217  * Passing this flag will provide individual stats for your
218  * @c kalloc_type_view that is defined.
219  *
220  * @const KT_SHARED_ACCT
221  * Passing this flag will accumulate stats as a part of the
222  * zone that your @c kalloc_type_view points to.
223  *
224  * @const KT_DATA_ONLY
225  * Represents that the type is "data-only". Adopters should not
226  * set this flag manually, it is meant for the compiler to set
227  * automatically when KALLOC_TYPE_CHECK(DATA) passes.
228  *
229  * @const KT_VM
230  * Represents that the type is large enough to use the VM. Adopters
231  * should not set this flag manually, it is meant for the compiler
232  * to set automatically when KALLOC_TYPE_VM_SIZE_CHECK passes.
233  *
234  * @const KT_PTR_ARRAY
235  * Represents that the type is an array of pointers. Adopters should not
236  * set this flag manually, it is meant for the compiler to set
237  * automatically when KALLOC_TYPE_CHECK(PTR) passes.
238  *
239  * @const KT_CHANGED*
240  * Represents a change in the version of the kalloc_type_view. This
241  * is required inorder to decouple requiring kexts to be rebuilt to
242  * use the new defintions right away. This flags should not be used
243  * manually at a callsite, it is meant for internal use only. Future
244  * changes to kalloc_type_view defintion should toggle this flag.
245  *
246  #if XNU_KERNEL_PRIVATE
247  * @const KT_NOSHARED
248  * This flags will force the callsite to bypass the shared zone and
249  * directly allocate from the assigned zone. This can only be used
250  * with KT_PRIV_ACCT right now. If you still require this behavior
251  * but don't want private stats use Z_SET_NOTSHARED at the allocation
252  * callsite instead.
253  *
254  * @const KT_SLID
255  * To indicate that strings in the view were slid during early boot.
256  *
257  * @const KT_PROCESSED
258  * This flag is set once the view is parse during early boot. Views
259  * that are not in BootKC on macOS aren't parsed and therefore will
260  * not have this flag set. The runtime can use this as an indication
261  * to appropriately redirect the call.
262  *
263  * @const KT_HASH
264  * Hash of signature used by kmem_*_guard to determine range and
265  * direction for allocation
266  #endif
267  */
268 __options_decl(kalloc_type_flags_t, uint32_t, {
269 	KT_DEFAULT        = 0x0001,
270 	KT_PRIV_ACCT      = 0x0002,
271 	KT_SHARED_ACCT    = 0x0004,
272 	KT_DATA_ONLY      = 0x0008,
273 	KT_VM             = 0x0010,
274 	KT_CHANGED        = 0x0020,
275 	KT_CHANGED2       = 0x0040,
276 	KT_PTR_ARRAY      = 0x0080,
277 #if XNU_KERNEL_PRIVATE
278 	KT_NOSHARED       = 0x2000,
279 	KT_SLID           = 0x4000,
280 	KT_PROCESSED      = 0x8000,
281 	KT_HASH           = 0xffff0000,
282 #endif
283 });
284 
285 /*!
286  * @typedef kalloc_type_view_t
287  *
288  * @abstract
289  * A kalloc type view is a structure used to redirect callers
290  * of @c kalloc_type to a particular zone based on the signature of
291  * their type.
292  *
293  * @discussion
294  * These structures are automatically created under the hood for every
295  * @c kalloc_type and @c kfree_type callsite. They are ingested during startup
296  * and are assigned zones based on the security policy for their signature.
297  *
298  * These structs are protected by the kernel lockdown and can't be initialized
299  * dynamically. They must be created using @c KALLOC_TYPE_DEFINE() or
300  * @c kalloc_type or @c kfree_type.
301  *
302  */
303 #if XNU_KERNEL_PRIVATE
304 struct kalloc_type_view {
305 	struct zone_view        kt_zv;
306 	const char             *kt_signature __unsafe_indexable;
307 	kalloc_type_flags_t     kt_flags;
308 	uint32_t                kt_size;
309 	zone_t                  kt_zshared;
310 	zone_t                  kt_zsig;
311 };
312 #else /* XNU_KERNEL_PRIVATE */
313 struct kalloc_type_view {
314 	struct zone_view        kt_zv;
315 	const char             *kt_signature __unsafe_indexable;
316 	kalloc_type_flags_t     kt_flags;
317 	uint32_t                kt_size;
318 	void                   *unused1;
319 	void                   *unused2;
320 };
321 #endif /* XNU_KERNEL_PRIVATE */
322 
323 /*
324  * The set of zones used by all kalloc heaps are defined by the constants
325  * below.
326  *
327  * KHEAP_START_SIZE: Size of the first sequential zone.
328  * KHEAP_MAX_SIZE  : Size of the last sequential zone.
329  * KHEAP_STEP_WIDTH: Number of zones created at every step (power of 2).
330  * KHEAP_STEP_START: Size of the first step.
331  * We also create some extra initial zones that don't follow the sequence
332  * for sizes 8 (on armv7 only), 16 and 32.
333  *
334  * idx step_increment   zone_elem_size
335  * 0       -                  16
336  * 1       -                  32
337  * 2       16                 48
338  * 3       16                 64
339  * 4       32                 96
340  * 5       32                 128
341  * 6       64                 192
342  * 7       64                 256
343  * 8       128                384
344  * 9       128                512
345  * 10      256                768
346  * 11      256                1024
347  * 12      512                1536
348  * 13      512                2048
349  * 14      1024               3072
350  * 15      1024               4096
351  * 16      2048               6144
352  * 17      2048               8192
353  * 18      4096               12288
354  * 19      4096               16384
355  * 20      8192               24576
356  * 21      8192               32768
357  */
358 #define kalloc_log2down(mask)   (31 - __builtin_clz(mask))
359 #define KHEAP_START_SIZE        32
360 #if  __x86_64__
361 #define KHEAP_MAX_SIZE          (16 * 1024)
362 #define KHEAP_EXTRA_ZONES       2
363 #else
364 #define KHEAP_MAX_SIZE          (32 * 1024)
365 #define KHEAP_EXTRA_ZONES       2
366 #endif
367 #define KHEAP_STEP_WIDTH        2
368 #define KHEAP_STEP_START        16
369 #define KHEAP_START_IDX         kalloc_log2down(KHEAP_START_SIZE)
370 #define KHEAP_NUM_STEPS         (kalloc_log2down(KHEAP_MAX_SIZE) - \
371 	                                kalloc_log2down(KHEAP_START_SIZE))
372 #define KHEAP_NUM_ZONES         (KHEAP_NUM_STEPS * KHEAP_STEP_WIDTH + \
373 	                                KHEAP_EXTRA_ZONES)
374 
375 /*!
376  * @enum kalloc_type_version_t
377  *
378  * @brief
379  * Enum that holds versioning information for @c kalloc_type_var_view
380  *
381  * @const KT_V1
382  * Version 1
383  *
384  */
385 __options_decl(kalloc_type_version_t, uint16_t, {
386 	KT_V1             = 0x0001,
387 });
388 
389 /*!
390  * @typedef kalloc_type_var_view_t
391  *
392  * @abstract
393  * This structure is analoguous to @c kalloc_type_view but handles
394  * @c kalloc_type callsites that are variable in size.
395  *
396  * @discussion
397  * These structures are automatically created under the hood for every
398  * variable sized @c kalloc_type and @c kfree_type callsite. They are ingested
399  * during startup and are assigned zones based on the security policy for
400  * their signature.
401  *
402  * These structs are protected by the kernel lockdown and can't be initialized
403  * dynamically. They must be created using @c KALLOC_TYPE_VAR_DEFINE() or
404  * @c kalloc_type or @c kfree_type.
405  *
406  */
407 struct kalloc_type_var_view {
408 	kalloc_type_version_t   kt_version;
409 	uint16_t                kt_size_hdr;
410 	/*
411 	 * Temporary: Needs to be 32bits cause we have many structs that use
412 	 * IONew/Delete that are larger than 32K.
413 	 */
414 	uint32_t                kt_size_type;
415 	zone_stats_t            kt_stats;
416 	const char             *__unsafe_indexable kt_name;
417 	zone_view_t             kt_next;
418 	zone_id_t               kt_heap_start;
419 	uint8_t                 kt_zones[KHEAP_NUM_ZONES];
420 	const char             * __unsafe_indexable kt_sig_hdr;
421 	const char             * __unsafe_indexable kt_sig_type;
422 	kalloc_type_flags_t     kt_flags;
423 };
424 
425 typedef struct kalloc_type_var_view *kalloc_type_var_view_t;
426 
427 /*!
428  * @macro KALLOC_TYPE_DECLARE
429  *
430  * @abstract
431  * (optionally) declares a kalloc type view (in a header).
432  *
433  * @param var           the name for the kalloc type view.
434  */
435 #define KALLOC_TYPE_DECLARE(var) \
436 	extern struct kalloc_type_view var[1]
437 
438 /*!
439  * @macro KALLOC_TYPE_DEFINE
440  *
441  * @abstract
442  * Defines a given kalloc type view with prefered accounting
443  *
444  * @discussion
445  * This macro allows you to define a kalloc type with private
446  * accounting. The defined kalloc_type_view can be used with
447  * kalloc_type_impl/kfree_type_impl to allocate/free memory.
448  * zalloc/zfree can also be used from inside xnu. However doing
449  * so doesn't handle freeing a NULL pointer or the use of tags.
450  *
451  * @param var           the name for the kalloc type view.
452  * @param type          the type of your allocation.
453  * @param flags         a @c KT_* flag.
454  */
455 #define KALLOC_TYPE_DEFINE(var, type, flags) \
456 	_KALLOC_TYPE_DEFINE(var, type, flags); \
457 	__ZONE_DECLARE_TYPE(var, type)
458 
459 /*!
460  * @macro KALLOC_TYPE_VAR_DECLARE
461  *
462  * @abstract
463  * (optionally) declares a kalloc type var view (in a header).
464  *
465  * @param var           the name for the kalloc type var view.
466  */
467 #define KALLOC_TYPE_VAR_DECLARE(var) \
468 	extern struct kalloc_type_var_view var[1]
469 
470 /*!
471  * @macro KALLOC_TYPE_VAR_DEFINE
472  *
473  * @abstract
474  * Defines a given kalloc type view with prefered accounting for
475  * variable sized typed allocations.
476  *
477  * @discussion
478  * As the views aren't yet being ingested, individual stats aren't
479  * available. The defined kalloc_type_var_view should be used with
480  * kalloc_type_var_impl/kfree_type_var_impl to allocate/free memory.
481  *
482  * This macro comes in 2 variants:
483  *
484  * 1. @c KALLOC_TYPE_VAR_DEFINE(var, e_ty, flags)
485  * 2. @c KALLOC_TYPE_VAR_DEFINE(var, h_ty, e_ty, flags)
486  *
487  * @param var           the name for the kalloc type var view.
488  * @param h_ty          the type of header in the allocation.
489  * @param e_ty          the type of repeating part in the allocation.
490  * @param flags         a @c KT_* flag.
491  */
492 #define KALLOC_TYPE_VAR_DEFINE(...) KALLOC_DISPATCH(KALLOC_TYPE_VAR_DEFINE, ##__VA_ARGS__)
493 
494 #ifdef XNU_KERNEL_PRIVATE
495 
496 /*
497  * These versions allow specifying the kalloc heap to allocate memory
498  * from
499  */
500 #define kheap_alloc_tag(kalloc_heap, size, flags, itag) \
501 	__kheap_alloc(kalloc_heap, size, __zone_flags_mix_tag(flags, itag), NULL)
502 #define kheap_alloc(kalloc_heap, size, flags) \
503 	kheap_alloc_tag(kalloc_heap, size, flags, VM_ALLOC_SITE_TAG())
504 
505 /*
506  * These versions should be used for allocating pure data bytes that
507  * do not contain any pointers
508  */
509 #define kalloc_data_tag(size, flags, itag) \
510 	kheap_alloc_tag(KHEAP_DATA_BUFFERS, size, flags, itag)
511 #define kalloc_data(size, flags) \
512 	kheap_alloc(KHEAP_DATA_BUFFERS, size, flags)
513 
514 #define krealloc_data_tag(elem, old_size, new_size, flags, itag) \
515 	__kheap_realloc(KHEAP_DATA_BUFFERS, elem, old_size, new_size, \
516 	    __zone_flags_mix_tag(flags, itag), NULL)
517 #define krealloc_data(elem, old_size, new_size, flags) \
518 	krealloc_data_tag(elem, old_size, new_size, flags, \
519 	    VM_ALLOC_SITE_TAG())
520 
521 #define kfree_data(elem, size) \
522 	kheap_free(KHEAP_DATA_BUFFERS, elem, size);
523 
524 #define kfree_data_addr(elem) \
525 	kheap_free_addr(KHEAP_DATA_BUFFERS, elem);
526 
527 extern void kheap_free_bounded(
528 	kalloc_heap_t heap,
529 	void         *addr __unsafe_indexable,
530 	vm_size_t     min_sz,
531 	vm_size_t     max_sz);
532 
533 extern void kalloc_data_require(
534 	void         *data __unsafe_indexable,
535 	vm_size_t     size);
536 
537 extern void kalloc_non_data_require(
538 	void         *data __unsafe_indexable,
539 	vm_size_t     size);
540 
541 #else /* XNU_KERNEL_PRIVATE */
542 
543 extern void *__sized_by(size) kalloc(
544 	vm_size_t           size) __attribute__((malloc, alloc_size(1)));
545 
546 extern void *__unsafe_indexable kalloc_data(
547 	vm_size_t           size,
548 	zalloc_flags_t      flags);
549 
550 __attribute__((malloc, alloc_size(1)))
551 static inline void *
__sized_by(size)552 __sized_by(size)
553 __kalloc_data(vm_size_t size, zalloc_flags_t flags)
554 {
555 	void *addr = (kalloc_data)(size, flags);
556 	if (flags & Z_NOFAIL) {
557 		__builtin_assume(addr != NULL);
558 	}
559 	return addr;
560 }
561 
562 #define kalloc_data(size, fl) __kalloc_data(size, fl)
563 
564 extern void *__unsafe_indexable krealloc_data(
565 	void               *ptr __unsafe_indexable,
566 	vm_size_t           old_size,
567 	vm_size_t           new_size,
568 	zalloc_flags_t      flags);
569 
570 __attribute__((malloc, alloc_size(3)))
571 static inline void *
__sized_by(new_size)572 __sized_by(new_size)
573 __krealloc_data(
574 	void               *ptr __sized_by(old_size),
575 	vm_size_t           old_size,
576 	vm_size_t           new_size,
577 	zalloc_flags_t      flags)
578 {
579 	void *addr = (krealloc_data)(ptr, old_size, new_size, flags);
580 	if (flags & Z_NOFAIL) {
581 		__builtin_assume(addr != NULL);
582 	}
583 	return addr;
584 }
585 
586 #define krealloc_data(ptr, old_size, new_size, fl) \
587 	__krealloc_data(ptr, old_size, new_size, fl)
588 
589 extern void kfree(
590 	void               *data __unsafe_indexable,
591 	vm_size_t           size);
592 
593 extern void kfree_data(
594 	void               *ptr __unsafe_indexable,
595 	vm_size_t           size);
596 
597 extern void kfree_data_addr(
598 	void               *ptr __unsafe_indexable);
599 
600 #endif /* !XNU_KERNEL_PRIVATE */
601 
602 /*!
603  * @macro kalloc_type
604  *
605  * @abstract
606  * Allocates element of a particular type
607  *
608  * @discussion
609  * This family of allocators segregate kalloc allocations based on their type.
610  *
611  * This macro comes in 3 variants:
612  *
613  * 1. @c kalloc_type(type, flags)
614  *    Use this macro for fixed sized allocation of a particular type.
615  *
616  * 2. @c kalloc_type(e_type, count, flags)
617  *    Use this macro for variable sized allocations that form an array,
618  *    do note that @c kalloc_type(e_type, 1, flags) is not equivalent to
619  *    @c kalloc_type(e_type, flags).
620  *
621  * 3. @c kalloc_type(hdr_type, e_type, count, flags)
622  *    Use this macro for variable sized allocations formed with
623  *    a header of type @c hdr_type followed by a variable sized array
624  *    with elements of type @c e_type, equivalent to this:
625  *
626  *    <code>
627  *    struct {
628  *        hdr_type hdr;
629  *        e_type   arr[];
630  *    }
631  *    </code>
632  *
633  * @param flags         @c zalloc_flags_t that get passed to zalloc_internal
634  */
635 #define kalloc_type(...)  KALLOC_DISPATCH(kalloc_type, ##__VA_ARGS__)
636 
637 /*!
638  * @macro kfree_type
639  *
640  * @abstract
641  * Allocates element of a particular type
642  *
643  * @discussion
644  * This pairs with the @c kalloc_type() that was made to allocate this element.
645  * Arguments passed to @c kfree_type() must match the one passed at allocation
646  * time precisely.
647  *
648  * This macro comes in the same 3 variants kalloc_type() does:
649  *
650  * 1. @c kfree_type(type, elem)
651  * 2. @c kfree_type(e_type, count, elem)
652  * 3. @c kfree_type(hdr_type, e_type, count, elem)
653  *
654  * @param elem          The address of the element to free
655  */
656 #define kfree_type(...)  KALLOC_DISPATCH(kfree_type, ##__VA_ARGS__)
657 
658 #ifdef XNU_KERNEL_PRIVATE
659 #define kalloc_type_tag(...)     KALLOC_DISPATCH(kalloc_type_tag, ##__VA_ARGS__)
660 #define krealloc_type_tag(...)   KALLOC_DISPATCH(krealloc_type_tag, ##__VA_ARGS__)
661 #define krealloc_type(...)       KALLOC_DISPATCH(krealloc_type, ##__VA_ARGS__)
662 
663 /*
664  * kalloc_type_require can't be made available to kexts as the
665  * kalloc_type_view's zone could be NULL in the following cases:
666  * - Size greater than KALLOC_SAFE_ALLOC_SIZE
667  * - On macOS, if call is not in BootKC
668  * - All allocations in kext for armv7
669  */
670 #define kalloc_type_require(type, value) ({                                    \
671 	static _KALLOC_TYPE_DEFINE(kt_view_var, type, KT_SHARED_ACCT);         \
672 	zone_require(kt_view_var->kt_zv.zv_zone, value);                       \
673 })
674 
675 #endif
676 
677 /*!
678  * @enum kt_granule_t
679  *
680  * @brief
681  * Granule encodings used by the compiler for the type signature.
682  *
683  * @discussion
684  * Given a type, the XNU signature type system (__builtin_xnu_type_signature)
685  * produces a signature by analyzing its memory layout, in chunks of 8 bytes,
686  * which we call granules. The encoding produced for each granule is the
687  * bitwise or of the encodings of all the types of the members included
688  * in that granule.
689  *
690  * @const KT_GRANULE_PADDING
691  * Represents padding inside a record type.
692  *
693  * @const KT_GRANULE_POINTER
694  * Represents a pointer type.
695  *
696  * @const KT_GRANULE_DATA
697  * Represents a scalar type that is not a pointer.
698  *
699  * @const KT_GRANULE_DUAL
700  * Currently unused.
701  *
702  * @const KT_GRANULE_PAC
703  * Represents a pointer which is subject to PAC.
704  */
705 __options_decl(kt_granule_t, uint32_t, {
706 	KT_GRANULE_PADDING = 0,
707 	KT_GRANULE_POINTER = 1,
708 	KT_GRANULE_DATA    = 2,
709 	KT_GRANULE_DUAL    = 4,
710 	KT_GRANULE_PAC     = 8
711 });
712 
713 #define KT_GRANULE_MAX                                                \
714 	(KT_GRANULE_PADDING | KT_GRANULE_POINTER | KT_GRANULE_DATA |  \
715 	    KT_GRANULE_DUAL | KT_GRANULE_PAC)
716 
717 /*
718  * Convert a granule encoding to the index of the bit that
719  * represents such granule in the type summary.
720  *
721  * The XNU type summary (__builtin_xnu_type_summary) produces a 32-bit
722  * summary of the type signature of a given type. If the bit at index
723  * (1 << G) is set in the summary, that means that the type contains
724  * one or more granules with encoding G.
725  */
726 #define KT_SUMMARY_GRANULE_TO_IDX(g)  (1UL << (g))
727 
728 #define KT_SUMMARY_MASK_TYPE_BITS  (0xffff)
729 
730 #define KT_SUMMARY_MASK_DATA                             \
731 	(KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_PADDING) |  \
732 	    KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_DATA))
733 
734 #define KT_SUMMARY_MASK_PTR                              \
735 	(KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_PADDING) |     \
736 	    KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_POINTER) |  \
737 	    KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_PAC))
738 
739 #define KT_SUMMARY_MASK_ALL_GRANULES                        \
740 	(KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_PADDING) |     \
741 	    KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_POINTER) |  \
742 	    KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_DATA) |     \
743 	    KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_DUAL) |     \
744 	    KT_SUMMARY_GRANULE_TO_IDX(KT_GRANULE_PAC))
745 
746 /*!
747  * @macro KT_SUMMARY_GRANULES
748  *
749  * @abstract
750  * Return the granule type summary for a given type
751  *
752  * @discussion
753  * This macro computes the type summary of a type, and it then extracts the
754  * bits which carry information about the granules in the memory layout.
755  *
756  * Note: you should never have to use __builtin_xnu_type_summary
757  * directly, as we reserve the right to use the remaining bits with
758  * different semantics.
759  *
760  * @param type          The type to analyze
761  */
762 #define KT_SUMMARY_GRANULES(type) \
763 	(__builtin_xnu_type_summary(type) & KT_SUMMARY_MASK_TYPE_BITS)
764 
765 /*!
766  * @macro KALLOC_TYPE_SIG_CHECK
767  *
768  * @abstract
769  * Return whether a given type is only made up of granules specified in mask
770  *
771  * @param mask          Granules to check for
772  * @param type          The type to analyze
773  */
774 #define KALLOC_TYPE_SIG_CHECK(mask, type) \
775 	((KT_SUMMARY_GRANULES(type) & ~(mask)) == 0)
776 
777 /*!
778  * @macro KALLOC_TYPE_IS_DATA_ONLY
779  *
780  * @abstract
781  * Return whether a given type is considered a data-only type.
782  *
783  * @param type          The type to analyze
784  */
785 #define KALLOC_TYPE_IS_DATA_ONLY(type) \
786 	KALLOC_TYPE_SIG_CHECK(KT_SUMMARY_MASK_DATA, type)
787 
788 /*!
789  * @macro KALLOC_TYPE_HAS_OVERLAPS
790  *
791  * @abstract
792  * Return whether a given type has overlapping granules.
793  *
794  * @discussion
795  * This macro returns whether the memory layout for a given type contains
796  * overlapping granules. An overlapping granule is a granule which includes
797  * members with types that have different encodings under the XNU signature
798  * type system.
799  *
800  * @param type          The type to analyze
801  */
802 #define KALLOC_TYPE_HAS_OVERLAPS(type) \
803 	((KT_SUMMARY_GRANULES(type) & ~KT_SUMMARY_MASK_ALL_GRANULES) != 0)
804 
805 /*!
806  * @macro KALLOC_TYPE_IS_COMPATIBLE_PTR
807  *
808  * @abstract
809  * Return whether pointer is compatible with a given type, in the XNU
810  * signature type system.
811  *
812  * @discussion
813  * This macro returns whether type pointed to by @c ptr is either the same
814  * type as @c type, or it has the same signature. The implementation relies
815  * on the @c __builtin_xnu_types_compatible builtin, and the value returned
816  * can be evaluated at compile time in both C and C++.
817  *
818  * Note: void pointers are treated as wildcards, and are thus compatible
819  * with any given type.
820  *
821  * @param ptr           the pointer whose type needs to be checked.
822  * @param type          the type which the pointer will be checked against.
823  */
824 #define KALLOC_TYPE_IS_COMPATIBLE_PTR(ptr, type)                   \
825 	_Pragma("clang diagnostic push")                               \
826 	_Pragma("clang diagnostic ignored \"-Wvoid-ptr-dereference\"") \
827 	(__builtin_xnu_types_compatible(__typeof__(*(ptr)), type) ||   \
828 	    __builtin_xnu_types_compatible(__typeof__(*(ptr)), void))  \
829 	_Pragma("clang diagnostic pop")
830 
831 #define KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(ptr, type) \
832 	_Static_assert(KALLOC_TYPE_IS_COMPATIBLE_PTR(ptr, type), \
833 	    "Pointer type is not compatible with specified type")
834 
835 
836 /*!
837  * @const KALLOC_ARRAY_SIZE_MAX
838  *
839  * @brief
840  * The maximum size that can be allocated with the @c KALLOC_ARRAY interface.
841  *
842  * @discussion
843  * This size is:
844  * - ~256M on 4k or PAC systems with 16k pages
845  * - ~1G on other 16k systems.
846  */
847 #if __arm64e__ || KASAN_TBI
848 #define KALLOC_ARRAY_SIZE_MAX   ((uint32_t)PAGE_MASK << PAGE_SHIFT)
849 #define KALLOC_ARRAY_GRANULE    32ul
850 #else
851 #define KALLOC_ARRAY_SIZE_MAX   ((uint32_t)UINT16_MAX << PAGE_SHIFT)
852 #define KALLOC_ARRAY_GRANULE    16ul
853 #endif
854 
855 /*!
856  * @macro KALLOC_ARRAY_TYPE_DECL
857  *
858  * @brief
859  * Declares a type used as a packed kalloc array type.
860  *
861  * @discussion
862  * This macro comes in two variants
863  *
864  * - KALLOC_ARRAY_TYPE_DECL(name, e_ty)
865  * - KALLOC_ARRAY_TYPE_DECL(name, h_ty, e_ty)
866  *
867  * The first one defines an array of elements of type @c e_ty,
868  * and the second a header of type @c h_ty followed by
869  * an array of elements of type @c e_ty.
870  *
871  * Those macros will then define the type @c ${name}_t as a typedef
872  * to a non existent structure type, in order to avoid accidental
873  * dereference of those pointers.
874  *
875  * kalloc array pointers are actually pointers that in addition to encoding
876  * the array base pointer, also encode the allocation size (only sizes
877  * up to @c KALLOC_ARRAY_SIZE_MAX bytes).
878  *
879  * Such pointers can be signed with data PAC properly, which will provide
880  * integrity of both the base pointer, and its size.
881  *
882  * kalloc arrays are useful to use instead of embedding the length
883  * of the allocation inside of itself, which tends to be driven by:
884  *
885  * - a desire to not grow the outer structure holding the pointer
886  *   to this array with an extra "length" field for optional arrays,
887  *   in order to save memory (see the @c ip_requests field in ports),
888  *
889  * - a need to be able to atomically consult the size of an allocation
890  *   with respect to loading its pointer (where address dependencies
891  *   traditionally gives this property) for lockless algorithms
892  *   (see the IPC space table).
893  *
894  * Using a kalloc array is preferable for two reasons:
895  *
896  * - embedding lengths inside the allocation is self-referential
897  *   and an appetizing target for post-exploitation strategies,
898  *
899  * - having a dependent load to get to the length loses out-of-order
900  *   opportunities for the CPU and prone to back-to-back cache misses.
901  *
902  * Holding information such as a level of usage of this array
903  * within itself is fine provided those quantities are validated
904  * against the "count" (number of elements) or "size" (allocation
905  * size in bytes) of the array before use.
906  *
907  *
908  * This macro will define a series of functions:
909  *
910  * - ${name}_count_to_size() and ${name}_size_to_count()
911  *   to convert between memory sizes and array element counts
912  *   (taking the header size into account when it exists);
913  *
914  *   Note that those functions assume the count/size are corresponding
915  *   to a valid allocation size within [0, KALLOC_ARRAY_SIZE_MAX].
916  *
917  * - ${name}_next_size() to build good allocation growth policies;
918  *
919  * - ${name}_base() returning a (bound-checked indexable) pointer
920  *   to the header of the array (or its first element when there is
921  *   no header);
922  *
923  * - ${name}_begin() returning a (bound-checked indexable)
924  *   pointer to the first element of the the array;
925  *
926  * - ${name}_contains() to check if an element index is within
927  *   the valid range of this allocation;
928  *
929  * - ${name}_next_elem() to get the next element of an array.
930  *
931  * - ${name}_get() and ${name}_get_nocheck() to return a pointer
932  *   to a given cell of the array with (resp. without) a bound
933  *   check against the array size. The bound-checked variant
934  *   returns NULL for invalid indexes.
935  *
936  * - ${name}_alloc_by_count() and ${name}_alloc_by_size()
937  *   to allocate a new array able to hold at least that many elements
938  *   (resp. bytes).
939  *
940  * - ${name}_realloc_by_count() and ${name}_realloc_by_size()
941  *   to re-allocate a new array able to hold at least that many elements
942  *   (resp. bytes).
943  *
944  * - ${name}_free() and ${name}_free_noclear() to free such an array
945  *   (resp. without nil-ing the pointer). The non-clearing variant
946  *   is to be used only when nil-ing out the pointer is otherwise
947  *   not allowed by C (const value, unable to take address of, ...),
948  *   otherwise the normal ${name}_free() must be used.
949  */
950 #define KALLOC_ARRAY_TYPE_DECL(...) \
951 	KALLOC_DISPATCH(KALLOC_ARRAY_TYPE_DECL, ##__VA_ARGS__)
952 
953 #if XNU_KERNEL_PRIVATE
954 
955 #define KALLOC_ARRAY_TYPE_DECL_(name, h_type_t, h_sz, e_type_t, e_sz) \
956 	KALLOC_TYPE_VAR_DECLARE(name ## _kt_view);                              \
957 	typedef struct name * __unsafe_indexable name ## _t;                    \
958                                                                                 \
959 	__pure2                                                                 \
960 	static inline uint32_t                                                  \
961 	name ## _count_to_size(uint32_t count)                                  \
962 	{                                                                       \
963 	        return (uint32_t)((h_sz) + (e_sz) * count);                     \
964 	}                                                                       \
965                                                                                 \
966 	__pure2                                                                 \
967 	static inline uint32_t                                                  \
968 	name ## _size_to_count(vm_size_t size)                                  \
969 	{                                                                       \
970 	        return (uint32_t)((size - (h_sz)) / (e_sz));                    \
971 	}                                                                       \
972                                                                                 \
973 	__pure2                                                                 \
974 	static inline uint32_t                                                  \
975 	name ## _size(name ## _t array)                                         \
976 	{                                                                       \
977 	        return __kalloc_array_size((vm_address_t)array);                \
978 	}                                                                       \
979                                                                                 \
980 	__pure2                                                                 \
981 	static inline uint32_t                                                  \
982 	name ## _next_size(                                                     \
983 	        uint32_t                min_count,                              \
984 	        vm_size_t               cur_size,                               \
985 	        uint32_t                vm_period)                              \
986 	{                                                                       \
987 	        vm_size_t size;                                                 \
988                                                                                 \
989 	        if (cur_size) {                                                 \
990 	                size = cur_size + (e_sz) - 1;                           \
991 	        } else {                                                        \
992 	                size = kt_size(h_sz, e_sz, min_count) - 1;              \
993 	        }                                                               \
994 	        size  = kalloc_next_good_size(size, vm_period);                 \
995 	        if (size <= KALLOC_ARRAY_SIZE_MAX) {                            \
996 	               return (uint32_t)size;                                   \
997 	        }                                                               \
998 	        return 2 * KALLOC_ARRAY_SIZE_MAX; /* will fail */               \
999 	}                                                                       \
1000                                                                                 \
1001 	__pure2                                                                 \
1002 	static inline uint32_t                                                  \
1003 	name ## _count(name ## _t array)                                        \
1004 	{                                                                       \
1005 	        return name ## _size_to_count(name ## _size(array));            \
1006 	}                                                                       \
1007                                                                                 \
1008 	__pure2                                                                 \
1009 	static inline h_type_t *__header_bidi_indexable                         \
1010 	name ## _base(name ## _t array)                                         \
1011 	{                                                                       \
1012 	        vm_address_t base = __kalloc_array_base((vm_address_t)array);   \
1013 	        uint32_t     size = __kalloc_array_size((vm_address_t)array);   \
1014                                                                                 \
1015 	        (void)size;                                                     \
1016 	        return __unsafe_forge_bidi_indexable(h_type_t *, base, size);   \
1017 	}                                                                       \
1018                                                                                 \
1019 	__pure2                                                                 \
1020 	static inline e_type_t *__header_bidi_indexable                         \
1021 	name ## _begin(name ## _t array)                                        \
1022 	{                                                                       \
1023 	        vm_address_t base = __kalloc_array_base((vm_address_t)array);   \
1024 	        uint32_t     size = __kalloc_array_size((vm_address_t)array);   \
1025                                                                                 \
1026 	        (void)size;                                                     \
1027 	        return __unsafe_forge_bidi_indexable(e_type_t *, base, size);   \
1028 	}                                                                       \
1029                                                                                 \
1030 	__pure2                                                                 \
1031 	static inline e_type_t *                                                \
1032 	name ## _next_elem(name ## _t array, e_type_t *e)                       \
1033 	{                                                                       \
1034 	        vm_address_t end = __kalloc_array_end((vm_address_t)array);     \
1035 	        vm_address_t ptr = (vm_address_t)e + sizeof(e_type_t);          \
1036                                                                                 \
1037 	        if (ptr + sizeof(e_type_t) <= end) {                            \
1038 	                return __unsafe_forge_single(e_type_t *, ptr);          \
1039 	        }                                                               \
1040 	        return NULL;                                                    \
1041 	}                                                                       \
1042                                                                                 \
1043 	__pure2                                                                 \
1044 	static inline bool                                                      \
1045 	name ## _contains(name ## _t array, vm_size_t i)                        \
1046 	{                                                                       \
1047 	        vm_size_t offs = (e_sz) + (h_sz);                               \
1048 	        vm_size_t s;                                                    \
1049                                                                                 \
1050 	        if (__improbable(os_mul_and_add_overflow(i, e_sz, offs, &s))) { \
1051 	                return false;                                           \
1052 	        }                                                               \
1053 	        if (__improbable(s > name ## _size(array))) {                   \
1054 	                return false;                                           \
1055 	        }                                                               \
1056 	        return true;                                                    \
1057 	}                                                                       \
1058                                                                                 \
1059 	__pure2                                                                 \
1060 	static inline e_type_t * __single                                       \
1061 	name ## _get_nocheck(name ## _t array, vm_size_t i)                     \
1062 	{                                                                       \
1063 	        return name ## _begin(array) + i;                               \
1064 	}                                                                       \
1065                                                                                 \
1066 	__pure2                                                                 \
1067 	static inline e_type_t * __single                                       \
1068 	name ## _get(name ## _t array, vm_size_t i)                             \
1069 	{                                                                       \
1070 	        if (__probable(name ## _contains(array, i))) {                  \
1071 	            return name ## _get_nocheck(array, i);                      \
1072 	        }                                                               \
1073 	        return NULL;                                                    \
1074 	}                                                                       \
1075                                                                                 \
1076 	static inline name ## _t                                                \
1077 	name ## _alloc_by_size(vm_size_t size, zalloc_flags_t fl)               \
1078 	{                                                                       \
1079 	        fl |= Z_KALLOC_ARRAY;                                           \
1080 	        fl = __zone_flags_mix_tag(fl, VM_ALLOC_SITE_TAG());             \
1081 	        return (name ## _t)kalloc_type_var_impl(name ## _kt_view,       \
1082 	                        size, fl, NULL);                                \
1083 	}                                                                       \
1084                                                                                 \
1085 	static inline name ## _t                                                \
1086 	name ## _alloc_by_count(uint32_t count, zalloc_flags_t fl)              \
1087 	{                                                                       \
1088 	        return name ## _alloc_by_size(kt_size(h_sz, e_sz, count), fl);  \
1089 	}                                                                       \
1090                                                                                 \
1091 	static inline name ## _t                                                \
1092 	name ## _realloc_by_size(                                               \
1093 	        name ## _t              array,                                  \
1094 	        vm_size_t               new_size,                               \
1095 	        zalloc_flags_t          fl)                                     \
1096 	{                                                                       \
1097 	        vm_address_t base = __kalloc_array_base((vm_address_t)array);   \
1098 	        vm_size_t    size = __kalloc_array_size((vm_address_t)array);   \
1099                                                                                 \
1100 	        fl |= Z_KALLOC_ARRAY;                                           \
1101 	        fl = __zone_flags_mix_tag(fl, VM_ALLOC_SITE_TAG());             \
1102 	        return (name ## _t)(krealloc_ext)(                              \
1103 	                        kt_mangle_var_view(name ## _kt_view),           \
1104 	                        (void *)base, size, new_size, fl, NULL).addr;   \
1105 	}                                                                       \
1106                                                                                 \
1107 	static inline name ## _t                                                \
1108 	name ## _realloc_by_count(                                              \
1109 	        name ## _t              array,                                  \
1110 	        uint32_t                new_count,                              \
1111 	        zalloc_flags_t          fl)                                     \
1112 	{                                                                       \
1113 	        vm_size_t new_size = kt_size(h_sz, e_sz, new_count);            \
1114                                                                                 \
1115 	        return name ## _realloc_by_size(array, new_size, fl);           \
1116 	}                                                                       \
1117                                                                                 \
1118 	static inline void                                                      \
1119 	name ## _free_noclear(name ## _t array)                                 \
1120 	{                                                                       \
1121 	        kfree_type_var_impl(name ## _kt_view,                           \
1122 	            name ## _base(array), name ## _size(array));                \
1123 	}                                                                       \
1124                                                                                 \
1125 	static inline void                                                      \
1126 	name ## _free(name ## _t *arrayp)                                       \
1127 	{                                                                       \
1128 	        name ## _t array = *arrayp;                                     \
1129                                                                                 \
1130 	        *arrayp = NULL;                                                 \
1131 	        kfree_type_var_impl(name ## _kt_view,                           \
1132 	            name ## _base(array), name ## _size(array));                \
1133 	}
1134 
1135 
1136 /*!
1137  * @macro KALLOC_ARRAY_TYPE_DEFINE()
1138  *
1139  * @description
1140  * Defines the data structures required to pair with a KALLOC_ARRAY_TYPE_DECL()
1141  * kalloc array declaration.
1142  *
1143  * @discussion
1144  * This macro comes in two variants
1145  *
1146  * - KALLOC_ARRAY_TYPE_DEFINE(name, e_ty, flags)
1147  * - KALLOC_ARRAY_TYPE_DEFINE(name, h_ty, e_ty, flags)
1148  *
1149  * Those must pair with the KALLOC_ARRAY_TYPE_DECL() form being used.
1150  * The flags must be valid @c kalloc_type_flags_t flags.
1151  */
1152 #define KALLOC_ARRAY_TYPE_DEFINE(...) \
1153 	KALLOC_DISPATCH(KALLOC_ARRAY_TYPE_DEFINE, ##__VA_ARGS__)
1154 
1155 /*!
1156  * @function kalloc_next_good_size()
1157  *
1158  * @brief
1159  * Allows to implement "allocation growth policies" that work well
1160  * with the allocator.
1161  *
1162  * @discussion
1163  * Note that if the caller tracks a number of elements for an array,
1164  * where the elements are of size S, and the current count is C,
1165  * then it is possible for kalloc_next_good_size(C * S, ..) to hit
1166  * a fixed point, clients must call with a size at least of ((C + 1) * S).
1167  *
1168  * @param size         the current "size" of the allocation (in bytes).
1169  * @param period       the "period" (power of 2) for the allocation growth
1170  *                     policy once hitting the VM sized allocations.
1171  */
1172 extern vm_size_t kalloc_next_good_size(
1173 	vm_size_t               size,
1174 	uint32_t                period);
1175 
1176 #pragma mark kalloc_array implementation details
1177 
1178 #define KALLOC_ARRAY_TYPE_DECL_2(name, e_type_t) \
1179 	KALLOC_ARRAY_TYPE_DECL_(name, e_type_t, 0, e_type_t, sizeof(e_type_t))
1180 
1181 #define KALLOC_ARRAY_TYPE_DECL_3(name, h_type_t, e_type_t) \
1182 	KALLOC_ARRAY_TYPE_DECL_(name, e_type_t, 0, e_type_t, sizeof(e_type_t))
1183 
1184 #define KALLOC_ARRAY_TYPE_DEFINE_3(name, e_type_t, flags) \
1185 	KALLOC_TYPE_VAR_DEFINE_3(name ## _kt_view, e_type_t, flags)
1186 
1187 #define KALLOC_ARRAY_TYPE_DEFINE_4(name, h_type_t, e_type_t, flags) \
1188 	KALLOC_TYPE_VAR_DEFINE_4(name ## _kt_view, h_type_t, e_type_t, flags)
1189 
1190 extern struct kalloc_result __kalloc_array_decode(
1191 	vm_address_t            array) __pure2;
1192 
1193 __pure2
1194 static inline uint32_t
__kalloc_array_size(vm_address_t array)1195 __kalloc_array_size(vm_address_t array)
1196 {
1197 	vm_address_t size = __kalloc_array_decode(array).size;
1198 
1199 	__builtin_assume(size <= KALLOC_ARRAY_SIZE_MAX);
1200 	return (uint32_t)size;
1201 }
1202 
1203 __pure2
1204 static inline vm_address_t
__kalloc_array_base(vm_address_t array)1205 __kalloc_array_base(vm_address_t array)
1206 {
1207 	return (vm_address_t)__kalloc_array_decode(array).addr;
1208 }
1209 
1210 __pure2
1211 static inline vm_address_t
__kalloc_array_begin(vm_address_t array,vm_size_t hdr_size)1212 __kalloc_array_begin(vm_address_t array, vm_size_t hdr_size)
1213 {
1214 	return (vm_address_t)__kalloc_array_decode(array).addr + hdr_size;
1215 }
1216 
1217 __pure2
1218 static inline vm_address_t
__kalloc_array_end(vm_address_t array)1219 __kalloc_array_end(vm_address_t array)
1220 {
1221 	struct kalloc_result kr = __kalloc_array_decode(array);
1222 
1223 	return (vm_address_t)kr.addr + kr.size;
1224 }
1225 
1226 #else /* !XNU_KERNEL_PRIVATE */
1227 
1228 #define KALLOC_ARRAY_TYPE_DECL_(name, h_type_t, h_sz, e_type_t, e_sz) \
1229 	typedef struct name * __unsafe_indexable name ## _t
1230 
1231 #endif /* !XNU_KERNEL_PRIVATE */
1232 #pragma mark implementation details
1233 
1234 
1235 static inline void *__unsafe_indexable
kt_mangle_var_view(kalloc_type_var_view_t kt_view)1236 kt_mangle_var_view(kalloc_type_var_view_t kt_view)
1237 {
1238 	return (void *__unsafe_indexable)((uintptr_t)kt_view | 1ul);
1239 }
1240 
1241 static inline kalloc_type_var_view_t __unsafe_indexable
kt_demangle_var_view(void * ptr)1242 kt_demangle_var_view(void *ptr)
1243 {
1244 	return (kalloc_type_var_view_t __unsafe_indexable)((uintptr_t)ptr & ~1ul);
1245 }
1246 
1247 #define kt_is_var_view(ptr)  ((uintptr_t)(ptr) & 1)
1248 
1249 static inline vm_size_t
kt_size(vm_size_t s1,vm_size_t s2,vm_size_t c2)1250 kt_size(vm_size_t s1, vm_size_t s2, vm_size_t c2)
1251 {
1252 	/* kalloc_large() will reject this size before even asking the VM  */
1253 	const vm_size_t limit = 1ull << (8 * sizeof(vm_size_t) - 1);
1254 
1255 	if (os_mul_and_add_overflow(s2, c2, s1, &s1) || (s1 & limit)) {
1256 		return limit;
1257 	}
1258 	return s1;
1259 }
1260 
1261 #define kalloc_type_2(type, flags) ({                                          \
1262 	static _KALLOC_TYPE_DEFINE(kt_view_var, type, KT_SHARED_ACCT);         \
1263 	__unsafe_forge_single(type *, kalloc_type_impl(kt_view_var, flags));   \
1264 })
1265 
1266 #define kfree_type_2(type, elem) ({                                            \
1267 	KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(elem, type);                     \
1268 	static _KALLOC_TYPE_DEFINE(kt_view_var, type, KT_SHARED_ACCT);         \
1269 	kfree_type_impl(kt_view_var, os_ptr_load_and_erase(elem));             \
1270 })
1271 
1272 #define kfree_type_3(type, count, elem) ({                                     \
1273 	KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(elem, type);                     \
1274 	static KALLOC_TYPE_VAR_DEFINE_3(kt_view_var, type, KT_SHARED_ACCT);    \
1275 	__auto_type __kfree_count = (count);                                   \
1276 	kfree_type_var_impl(kt_view_var, os_ptr_load_and_erase(elem),          \
1277 	    kt_size(0, sizeof(type), __kfree_count));                          \
1278 })
1279 
1280 #define kfree_type_4(hdr_ty, e_ty, count, elem) ({                             \
1281 	KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(elem, hdr_ty);                   \
1282 	static KALLOC_TYPE_VAR_DEFINE_4(kt_view_var, hdr_ty, e_ty,             \
1283 	    KT_SHARED_ACCT);                                                   \
1284 	__auto_type __kfree_count = (count);                                   \
1285 	kfree_type_var_impl(kt_view_var,                                       \
1286 	    os_ptr_load_and_erase(elem),                                       \
1287 	    kt_size(sizeof(hdr_ty), sizeof(e_ty), __kfree_count));             \
1288 })
1289 
1290 #ifdef XNU_KERNEL_PRIVATE
1291 #define kalloc_type_tag_3(type, flags, tag) ({                                 \
1292 	static _KALLOC_TYPE_DEFINE(kt_view_var, type, KT_SHARED_ACCT);         \
1293 	__unsafe_forge_single(type *, zalloc_flags(kt_view_var,                \
1294 	    Z_VM_TAG(flags, tag)));                                            \
1295 })
1296 
1297 #define kalloc_type_tag_4(type, count, flags, tag) ({                          \
1298 	static KALLOC_TYPE_VAR_DEFINE_3(kt_view_var, type, KT_SHARED_ACCT);    \
1299 	(type *)kalloc_type_var_impl(kt_view_var,                              \
1300 	    kt_size(0, sizeof(type), count),                                   \
1301 	    __zone_flags_mix_tag(flags, tag), NULL);                           \
1302 })
1303 #define kalloc_type_3(type, count, flags)  \
1304 	kalloc_type_tag_4(type, count, flags, VM_ALLOC_SITE_TAG())
1305 
1306 #define kalloc_type_tag_5(hdr_ty, e_ty, count, flags, tag) ({                  \
1307 	static KALLOC_TYPE_VAR_DEFINE_4(kt_view_var, hdr_ty, e_ty,             \
1308 	    KT_SHARED_ACCT);                                                   \
1309 	(hdr_ty *)kalloc_type_var_impl(kt_view_var,                            \
1310 	    kt_size(sizeof(hdr_ty), sizeof(e_ty), count),                      \
1311 	    __zone_flags_mix_tag(flags, tag), NULL);                           \
1312 })
1313 #define kalloc_type_4(hdr_ty, e_ty, count, flags) \
1314 	kalloc_type_tag_5(hdr_ty, e_ty, count, flags, VM_ALLOC_SITE_TAG())
1315 
1316 #define krealloc_type_tag_6(type, old_count, new_count, elem, flags, tag) ({   \
1317 	static KALLOC_TYPE_VAR_DEFINE_3(kt_view_var, type, KT_SHARED_ACCT);    \
1318 	KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(elem, type);                     \
1319 	(type *)__krealloc_type(kt_view_var, elem,                             \
1320 	    kt_size(0, sizeof(type), old_count),                               \
1321 	    kt_size(0, sizeof(type), new_count),                               \
1322 	    __zone_flags_mix_tag(flags, tag), NULL);                           \
1323 })
1324 #define krealloc_type_5(type, old_count, new_count, elem, flags) \
1325 	krealloc_type_tag_6(type, old_count, new_count, elem, flags, \
1326 	    VM_ALLOC_SITE_TAG())
1327 
1328 #define krealloc_type_tag_7(hdr_ty, e_ty, old_count, new_count, elem,          \
1329 	    flags, tag) ({                                                     \
1330 	static KALLOC_TYPE_VAR_DEFINE_4(kt_view_var, hdr_ty, e_ty,             \
1331 	    KT_SHARED_ACCT);                                                   \
1332 	KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(elem, hdr_ty);                   \
1333 	(hdr_ty *)__krealloc_type(kt_view_var, elem,                           \
1334 	    kt_size(sizeof(hdr_ty), sizeof(e_ty), old_count),                  \
1335 	    kt_size(sizeof(hdr_ty), sizeof(e_ty), new_count),                  \
1336 	    __zone_flags_mix_tag(flags, tag), NULL);                           \
1337 })
1338 #define krealloc_type_6(hdr_ty, e_ty, old_count, new_count, elem, flags) \
1339 	krealloc_type_tag_7(hdr_ty, e_ty, old_count, new_count, elem, flags,   \
1340 	    VM_ALLOC_SITE_TAG())
1341 
1342 #else /* XNU_KERNEL_PRIVATE */
1343 
1344 #define kalloc_type_3(type, count, flags) ({                                   \
1345 	_Static_assert((flags) == Z_WAITOK, "kexts can only pass Z_WAITOK");   \
1346 	static KALLOC_TYPE_VAR_DEFINE_3(kt_view_var, type, KT_SHARED_ACCT);    \
1347 	(type *)kalloc_type_var_impl(kt_view_var,                              \
1348 	    kt_size(0, sizeof(type), count), flags, NULL);                     \
1349 })
1350 
1351 #define kalloc_type_4(hdr_ty, e_ty, count, flags) ({                           \
1352 	_Static_assert((flags) == Z_WAITOK, "kexts can only pass Z_WAITOK");   \
1353 	static KALLOC_TYPE_VAR_DEFINE_4(kt_view_var, hdr_ty, e_ty,             \
1354 	    KT_SHARED_ACCT);                                                   \
1355 	(hdr_ty *)kalloc_type_var_impl(kt_view_var, kt_size(sizeof(hdr_ty),    \
1356 	    sizeof(e_ty), count), flags, NULL);                                \
1357 })
1358 
1359 #endif /* !XNU_KERNEL_PRIVATE */
1360 
1361 /*
1362  * All k*free macros set "elem" to NULL on free.
1363  *
1364  * Note: all values passed to k*free() might be in the element to be freed,
1365  *       temporaries must be taken, and the resetting to be done prior to free.
1366  */
1367 #ifdef XNU_KERNEL_PRIVATE
1368 
1369 #define kheap_free(heap, elem, size) ({                                        \
1370 	kalloc_heap_t __kfree_heap = (heap);                                   \
1371 	__auto_type __kfree_size = (size);                                     \
1372 	__builtin_assume(!kt_is_var_view(__kfree_heap));                       \
1373 	kfree_ext((void *)__kfree_heap,                                        \
1374 	    (void *)os_ptr_load_and_erase(elem), __kfree_size);                \
1375 })
1376 
1377 #define kheap_free_addr(heap, elem) ({                                         \
1378 	kalloc_heap_t __kfree_heap = (heap);                                   \
1379 	kfree_addr_ext(__kfree_heap, (void *)os_ptr_load_and_erase(elem));     \
1380 })
1381 
1382 #define kheap_free_bounded(heap, elem, min_sz, max_sz) ({                      \
1383 	static_assert(max_sz <= KALLOC_SAFE_ALLOC_SIZE);                       \
1384 	kalloc_heap_t __kfree_heap = (heap);                                   \
1385 	__auto_type __kfree_min_sz = (min_sz);                                 \
1386 	__auto_type __kfree_max_sz = (max_sz);                                 \
1387 	(kheap_free_bounded)(__kfree_heap,                                     \
1388 	    (void *)os_ptr_load_and_erase(elem),                               \
1389 	    __kfree_min_sz, __kfree_max_sz);                                   \
1390 })
1391 
1392 #else /* XNU_KERNEL_PRIVATE */
1393 
1394 #define kfree_data(elem, size) ({                                              \
1395 	__auto_type __kfree_size = (size);                                     \
1396 	(kfree_data)((void *)os_ptr_load_and_erase(elem), __kfree_size);       \
1397 })
1398 
1399 #define kfree_data_addr(elem) \
1400 	(kfree_data_addr)((void *)os_ptr_load_and_erase(elem))
1401 
1402 #endif /* !XNU_KERNEL_PRIVATE */
1403 
1404 #if __has_feature(address_sanitizer)
1405 # define __kalloc_no_kasan __attribute__((no_sanitize("address")))
1406 #else
1407 # define __kalloc_no_kasan
1408 #endif
1409 
1410 #define KALLOC_CONCAT(x, y) __CONCAT(x,y)
1411 
1412 #define KALLOC_COUNT_ARGS1(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, N, ...) N
1413 #define KALLOC_COUNT_ARGS(...) \
1414 	KALLOC_COUNT_ARGS1(, ##__VA_ARGS__, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
1415 #define KALLOC_DISPATCH1(base, N, ...) __CONCAT(base, N)(__VA_ARGS__)
1416 #define KALLOC_DISPATCH(base, ...) \
1417 	KALLOC_DISPATCH1(base, KALLOC_COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)
1418 #define KALLOC_DISPATCH1_R(base, N, ...) __CONCAT(base, N)(__VA_ARGS__)
1419 #define KALLOC_DISPATCH_R(base, ...) \
1420 	KALLOC_DISPATCH1_R(base, KALLOC_COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)
1421 
1422 #define kt_view_var \
1423 	KALLOC_CONCAT(kalloc_type_view_, __LINE__)
1424 
1425 #define KALLOC_TYPE_SEGMENT "__DATA_CONST"
1426 
1427 /*
1428  * When kalloc_type_impl is called from xnu, it calls zalloc_flags
1429  * directly and doesn't redirect zone-less sites to kheap_alloc.
1430  * Passing a size larger than KHEAP_MAX_SIZE for these allocations will
1431  * lead to a panic as the zone is null. Therefore assert that size
1432  * is less than KALLOC_SAFE_ALLOC_SIZE.
1433  */
1434 #ifdef XNU_KERNEL_PRIVATE
1435 #define KALLOC_TYPE_SIZE_CHECK(size)                           \
1436 	_Static_assert(size <= KALLOC_SAFE_ALLOC_SIZE,             \
1437 	"type is too large");
1438 #else
1439 #define KALLOC_TYPE_SIZE_CHECK(size)
1440 #endif
1441 
1442 #define KALLOC_TYPE_CHECK_2(check, type) \
1443 	(KALLOC_TYPE_SIG_CHECK(check, type))
1444 
1445 #define KALLOC_TYPE_CHECK_3(check, type1, type2) \
1446 	(KALLOC_TYPE_SIG_CHECK(check, type1) && \
1447 	    KALLOC_TYPE_SIG_CHECK(check, type2))
1448 
1449 #define KALLOC_TYPE_CHECK(...) \
1450 	KALLOC_DISPATCH_R(KALLOC_TYPE_CHECK, ##__VA_ARGS__)
1451 
1452 #define KALLOC_TYPE_VM_SIZE_CHECK_1(type) \
1453 	(sizeof(type) > KHEAP_MAX_SIZE)
1454 
1455 #define KALLOC_TYPE_VM_SIZE_CHECK_2(type1, type2) \
1456 	(sizeof(type1) + sizeof(type2) > KHEAP_MAX_SIZE)
1457 
1458 #define KALLOC_TYPE_VM_SIZE_CHECK(...) \
1459 	KALLOC_DISPATCH_R(KALLOC_TYPE_VM_SIZE_CHECK, ##__VA_ARGS__)
1460 
1461 #define KALLOC_TYPE_TRAILING_DATA_CHECK(hdr_ty, elem_ty)     \
1462 	_Static_assert((KALLOC_TYPE_IS_DATA_ONLY(hdr_ty) ||  \
1463 	    !KALLOC_TYPE_IS_DATA_ONLY(elem_ty)),             \
1464 	"cannot allocate data-only array of " #elem_ty       \
1465 	" contiguously to " #hdr_ty)
1466 
1467 #ifdef __cplusplus
1468 #define KALLOC_TYPE_CAST_FLAGS(flags) static_cast<kalloc_type_flags_t>(flags)
1469 #else
1470 #define KALLOC_TYPE_CAST_FLAGS(flags) (kalloc_type_flags_t)(flags)
1471 #endif
1472 
1473 /*
1474  * Don't emit signature if type is "data-only" or is large enough that it
1475  * uses the VM.
1476  *
1477  * Note: sig_type is the type you want to emit signature for. The variable
1478  * args can be used to provide other types in the allocation, to make the
1479  * decision of whether to emit the signature.
1480  */
1481 #define KALLOC_TYPE_EMIT_SIG(sig_type, ...)                              \
1482 	(KALLOC_TYPE_CHECK(KT_SUMMARY_MASK_DATA, sig_type, ##__VA_ARGS__) || \
1483 	KALLOC_TYPE_VM_SIZE_CHECK(sig_type, ##__VA_ARGS__))?                 \
1484 	"" : __builtin_xnu_type_signature(sig_type)
1485 
1486 /*
1487  * Kalloc type flags are adjusted to indicate if the type is "data-only" or
1488  * will use the VM or is a pointer array.
1489  */
1490 #define KALLOC_TYPE_ADJUST_FLAGS(flags, ...)                                 \
1491 	KALLOC_TYPE_CAST_FLAGS((flags | KT_CHANGED | KT_CHANGED2 |               \
1492 	(KALLOC_TYPE_CHECK(KT_SUMMARY_MASK_DATA, __VA_ARGS__)? KT_DATA_ONLY: 0) |\
1493 	(KALLOC_TYPE_CHECK(KT_SUMMARY_MASK_PTR, __VA_ARGS__)? KT_PTR_ARRAY: 0) | \
1494 	(KALLOC_TYPE_VM_SIZE_CHECK(__VA_ARGS__)? KT_VM : 0)))
1495 
1496 #define _KALLOC_TYPE_DEFINE(var, type, flags)                       \
1497 	__kalloc_no_kasan                                               \
1498 	__PLACE_IN_SECTION(KALLOC_TYPE_SEGMENT ", __kalloc_type, "      \
1499 	    "regular, live_support")                                    \
1500 	struct kalloc_type_view var[1] = { {                            \
1501 	    .kt_zv.zv_name = "site." #type,                             \
1502 	    .kt_flags = KALLOC_TYPE_ADJUST_FLAGS(flags, type),          \
1503 	    .kt_size = sizeof(type),                                    \
1504 	    .kt_signature = KALLOC_TYPE_EMIT_SIG(type),                 \
1505 	} };                                                            \
1506 	KALLOC_TYPE_SIZE_CHECK(sizeof(type));
1507 
1508 #define KALLOC_TYPE_VAR_DEFINE_3(var, type, flags)                  \
1509 	__kalloc_no_kasan                                               \
1510 	__PLACE_IN_SECTION(KALLOC_TYPE_SEGMENT ", __kalloc_var, "       \
1511 	    "regular, live_support")                                    \
1512 	struct kalloc_type_var_view var[1] = { {                        \
1513 	    .kt_version = KT_V1,                                        \
1514 	    .kt_name = "site." #type,                                   \
1515 	    .kt_flags = KALLOC_TYPE_ADJUST_FLAGS(flags, type),          \
1516 	    .kt_size_type = sizeof(type),                               \
1517 	    .kt_sig_type = KALLOC_TYPE_EMIT_SIG(type),                  \
1518 	} };                                                            \
1519 	KALLOC_TYPE_SIZE_CHECK(sizeof(type));
1520 
1521 #define KALLOC_TYPE_VAR_DEFINE_4(var, hdr, type, flags)             \
1522 	__kalloc_no_kasan                                               \
1523 	__PLACE_IN_SECTION(KALLOC_TYPE_SEGMENT ", __kalloc_var, "       \
1524 	    "regular, live_support")                                    \
1525 	struct kalloc_type_var_view var[1] = { {                        \
1526 	    .kt_version = KT_V1,                                        \
1527 	    .kt_name = "site." #hdr "." #type,                          \
1528 	    .kt_flags = KALLOC_TYPE_ADJUST_FLAGS(flags, hdr, type),     \
1529 	    .kt_size_hdr = sizeof(hdr),                                 \
1530 	    .kt_size_type = sizeof(type),                               \
1531 	    .kt_sig_hdr = KALLOC_TYPE_EMIT_SIG(hdr, type),              \
1532 	    .kt_sig_type = KALLOC_TYPE_EMIT_SIG(type, hdr),             \
1533 	} };                                                            \
1534 	KALLOC_TYPE_SIZE_CHECK(sizeof(hdr));                            \
1535 	KALLOC_TYPE_SIZE_CHECK(sizeof(type));                           \
1536 	KALLOC_TYPE_TRAILING_DATA_CHECK(hdr, type);
1537 
1538 #ifndef XNU_KERNEL_PRIVATE
1539 /*
1540  * This macro is currently used by AppleImage4
1541  */
1542 #define KALLOC_TYPE_DEFINE_SITE(var, type, flags)       \
1543 	static _KALLOC_TYPE_DEFINE(var, type, flags)
1544 
1545 #endif /* !XNU_KERNEL_PRIVATE */
1546 
1547 #ifdef XNU_KERNEL_PRIVATE
1548 
1549 extern struct kalloc_result kalloc_ext(
1550 	void                   *kheap_or_kt_view __unsafe_indexable,
1551 	vm_size_t               size,
1552 	zalloc_flags_t          flags,
1553 	void                   *site);
1554 
1555 static inline struct kalloc_result
__kalloc_ext(void * kheap_or_kt_view __unsafe_indexable,vm_size_t size,zalloc_flags_t flags,void * site)1556 __kalloc_ext(
1557 	void                   *kheap_or_kt_view __unsafe_indexable,
1558 	vm_size_t               size,
1559 	zalloc_flags_t          flags,
1560 	void                   *site)
1561 {
1562 	struct kalloc_result kr;
1563 
1564 	kr    = (kalloc_ext)(kheap_or_kt_view, size, flags, site);
1565 	if (flags & Z_NOFAIL) {
1566 		__builtin_assume(kr.addr != NULL);
1567 	}
1568 	return kr;
1569 }
1570 
1571 #define kalloc_ext(hov, size, fl, site) __kalloc_ext(hov, size, fl, site)
1572 
1573 extern void kfree_ext(
1574 	void                   *kheap_or_kt_view __unsafe_indexable,
1575 	void                   *addr __unsafe_indexable,
1576 	vm_size_t               size);
1577 
1578 // rdar://87559422
1579 static inline void *__unsafe_indexable
kalloc_type_var_impl(kalloc_type_var_view_t kt_view,vm_size_t size,zalloc_flags_t flags,void * site)1580 kalloc_type_var_impl(
1581 	kalloc_type_var_view_t    kt_view,
1582 	vm_size_t                 size,
1583 	zalloc_flags_t            flags,
1584 	void                      *site)
1585 {
1586 	struct kalloc_result kr;
1587 
1588 	kr = kalloc_ext(kt_mangle_var_view(kt_view), size, flags, site);
1589 	return kr.addr;
1590 }
1591 
1592 static inline void
kfree_type_var_impl(kalloc_type_var_view_t kt_view,void * ptr __unsafe_indexable,vm_size_t size)1593 kfree_type_var_impl(
1594 	kalloc_type_var_view_t      kt_view,
1595 	void                       *ptr __unsafe_indexable,
1596 	vm_size_t                   size)
1597 {
1598 	kfree_ext(kt_mangle_var_view(kt_view), ptr, size);
1599 }
1600 
1601 #else /* XNU_KERNEL_PRIVATE */
1602 
1603 extern void *__unsafe_indexable kalloc_type_var_impl(
1604 	kalloc_type_var_view_t  kt_view,
1605 	vm_size_t               size,
1606 	zalloc_flags_t          flags,
1607 	void                   *site);
1608 
1609 extern void kfree_type_var_impl(
1610 	kalloc_type_var_view_t  kt_view,
1611 	void                   *ptr __unsafe_indexable,
1612 	vm_size_t               size);
1613 
1614 #endif /* !XNU_KERNEL_PRIVATE */
1615 
1616 __attribute__((malloc, alloc_size(2)))
1617 static inline void *
__sized_by(size)1618 __sized_by(size)
1619 __kalloc_type_var_impl(
1620 	kalloc_type_var_view_t  kt_view,
1621 	vm_size_t               size,
1622 	zalloc_flags_t          flags,
1623 	void                   *site)
1624 {
1625 	void *__unsafe_indexable addr;
1626 
1627 	addr = (kalloc_type_var_impl)(kt_view, size, flags, site);
1628 	if (flags & Z_NOFAIL) {
1629 		__builtin_assume(addr != NULL);
1630 	}
1631 	return __unsafe_forge_bidi_indexable(void *, addr, size);
1632 }
1633 
1634 #define kalloc_type_var_impl(ktv, size, fl, site) \
1635 	__kalloc_type_var_impl(ktv, size, fl, site)
1636 
1637 extern void *kalloc_type_impl_external(
1638 	kalloc_type_view_t  kt_view,
1639 	zalloc_flags_t      flags);
1640 
1641 extern void kfree_type_impl_external(
1642 	kalloc_type_view_t  kt_view,
1643 	void               *ptr __unsafe_indexable);
1644 
1645 extern void *OSObject_typed_operator_new(
1646 	kalloc_type_view_t  ktv,
1647 	vm_size_t           size);
1648 
1649 extern void OSObject_typed_operator_delete(
1650 	kalloc_type_view_t  ktv,
1651 	void               *mem __unsafe_indexable,
1652 	vm_size_t           size);
1653 
1654 #ifdef XNU_KERNEL_PRIVATE
1655 #pragma GCC visibility push(hidden)
1656 
1657 #define KALLOC_TYPE_SIZE_MASK  0xffffff
1658 #define KALLOC_TYPE_IDX_SHIFT  24
1659 #define KALLOC_TYPE_IDX_MASK   0xff
1660 
1661 static inline uint32_t
kalloc_type_get_size(uint32_t kt_size)1662 kalloc_type_get_size(uint32_t kt_size)
1663 {
1664 	return kt_size & KALLOC_TYPE_SIZE_MASK;
1665 }
1666 
1667 extern bool IOMallocType_from_vm(
1668 	kalloc_type_view_t ktv);
1669 
1670 /* Used by kern_os_* and operator new */
1671 KALLOC_HEAP_DECLARE(KERN_OS_MALLOC);
1672 
1673 extern void kheap_startup_init(kalloc_heap_t heap);
1674 extern void kheap_var_startup_init(kalloc_heap_t heap);
1675 
1676 __attribute__((malloc, alloc_size(2)))
1677 static inline void *
__sized_by(size)1678 __sized_by(size)
1679 __kheap_alloc(
1680 	kalloc_heap_t           kheap,
1681 	vm_size_t               size,
1682 	zalloc_flags_t          flags,
1683 	void                   *site)
1684 {
1685 	struct kalloc_result kr;
1686 	__builtin_assume(!kt_is_var_view(kheap));
1687 	kr = kalloc_ext(kheap, size, flags, site);
1688 	return __unsafe_forge_bidi_indexable(void *, kr.addr, size);
1689 }
1690 
1691 extern struct kalloc_result krealloc_ext(
1692 	void                   *kheap_or_kt_view __unsafe_indexable,
1693 	void                   *addr __unsafe_indexable,
1694 	vm_size_t               old_size,
1695 	vm_size_t               new_size,
1696 	zalloc_flags_t          flags,
1697 	void                   *site);
1698 
1699 static inline struct kalloc_result
__krealloc_ext(void * kheap_or_kt_view __unsafe_indexable,void * addr __sized_by (old_size),vm_size_t old_size,vm_size_t new_size,zalloc_flags_t flags,void * site)1700 __krealloc_ext(
1701 	void                   *kheap_or_kt_view __unsafe_indexable,
1702 	void                   *addr __sized_by(old_size),
1703 	vm_size_t               old_size,
1704 	vm_size_t               new_size,
1705 	zalloc_flags_t          flags,
1706 	void                   *site)
1707 {
1708 	struct kalloc_result kr = (krealloc_ext)(kheap_or_kt_view, addr, old_size,
1709 	    new_size, flags, site);
1710 	if (flags & Z_NOFAIL) {
1711 		__builtin_assume(kr.addr != NULL);
1712 	}
1713 	return kr;
1714 }
1715 
1716 #define krealloc_ext(hov, addr, old_size, new_size, fl, site) \
1717 	__krealloc_ext(hov, addr, old_size, new_size, fl, site)
1718 
1719 __attribute__((malloc, alloc_size(4)))
1720 static inline void *
__sized_by(new_size)1721 __sized_by(new_size)
1722 __kheap_realloc(
1723 	kalloc_heap_t           kheap,
1724 	void                   *addr __sized_by(old_size),
1725 	vm_size_t               old_size,
1726 	vm_size_t               new_size,
1727 	zalloc_flags_t          flags,
1728 	void                   *site)
1729 {
1730 	struct kalloc_result kr;
1731 	__builtin_assume(!kt_is_var_view(kheap));
1732 	kr = krealloc_ext(kheap, addr, old_size, new_size, flags, site);
1733 	return __unsafe_forge_bidi_indexable(void *, kr.addr, new_size);
1734 }
1735 
1736 __attribute__((malloc, alloc_size(4)))
1737 static inline void *
__sized_by(new_size)1738 __sized_by(new_size)
1739 __krealloc_type(
1740 	kalloc_type_var_view_t  kt_view,
1741 	void                   *addr __sized_by(old_size),
1742 	vm_size_t               old_size,
1743 	vm_size_t               new_size,
1744 	zalloc_flags_t          flags,
1745 	void                   *site)
1746 {
1747 	struct kalloc_result kr;
1748 	kr = krealloc_ext(kt_mangle_var_view(kt_view), addr,
1749 	    old_size, new_size, flags, site);
1750 	return __unsafe_forge_bidi_indexable(void *, kr.addr, new_size);
1751 }
1752 
1753 extern void kfree_addr_ext(
1754 	kalloc_heap_t           kheap,
1755 	void                   *addr __unsafe_indexable);
1756 
1757 extern zone_t kalloc_zone_for_size(
1758 	zone_id_t             zid,
1759 	vm_size_t             size);
1760 
1761 extern vm_size_t kalloc_large_max;
1762 SCALABLE_COUNTER_DECLARE(kalloc_large_count);
1763 SCALABLE_COUNTER_DECLARE(kalloc_large_total);
1764 
1765 extern void kern_os_typed_free(
1766 	kalloc_type_view_t    ktv,
1767 	void                 *addr __unsafe_indexable,
1768 	vm_size_t             esize);
1769 
1770 #pragma GCC visibility pop
1771 #endif  /* !XNU_KERNEL_PRIVATE */
1772 
1773 extern void kern_os_zfree(
1774 	zone_t        zone,
1775 	void         *addr __unsafe_indexable,
1776 	vm_size_t     size);
1777 
1778 __ASSUME_PTR_ABI_SINGLE_END __END_DECLS
1779 
1780 #endif  /* _KERN_KALLOC_H_ */
1781 
1782 #endif  /* KERNEL_PRIVATE */
1783