1*0f4c859eSApple OSS Distributions# XNU Allocators best practices 2*0f4c859eSApple OSS Distributions 3*0f4c859eSApple OSS Distributions## Introduction 4*0f4c859eSApple OSS Distributions 5*0f4c859eSApple OSS DistributionsXNU proposes two ways to allocate memory: 6*0f4c859eSApple OSS Distributions 7*0f4c859eSApple OSS Distributions- the VM subsystem that provides allocations at the granularity of pages (with 8*0f4c859eSApple OSS Distributions `kmem_alloc` and similar interfaces); 9*0f4c859eSApple OSS Distributions- the zone allocator subsystem (`<kern/zalloc.h>`) which is a slab-allocator of 10*0f4c859eSApple OSS Distributions objects of fixed size. 11*0f4c859eSApple OSS Distributions 12*0f4c859eSApple OSS DistributionsIn addition to that, `<kern/kalloc.h>` provides a variable-size general purpose 13*0f4c859eSApple OSS Distributionsallocator implemented as a collection of zones of fixed size, and overflowing to 14*0f4c859eSApple OSS Distributions`kmem_alloc` for allocations larger than a few pages (32KB when this 15*0f4c859eSApple OSS Distributionsdocument was being written but this is subject to change/tuning in the future). 16*0f4c859eSApple OSS Distributions 17*0f4c859eSApple OSS Distributions 18*0f4c859eSApple OSS DistributionsThe Core Kernel allocators rely on the following headers: 19*0f4c859eSApple OSS Distributions 20*0f4c859eSApple OSS Distributions- `<kern/zalloc.h>` and `<kern/kalloc.h>` for its API surface, which most 21*0f4c859eSApple OSS Distributions clients should find sufficient, 22*0f4c859eSApple OSS Distributions- `<kern/zalloc_internal.h>` for interfaces that need to be exported 23*0f4c859eSApple OSS Distributions for introspection and implementation purposes, and is not meant 24*0f4c859eSApple OSS Distributions for general consumption. 25*0f4c859eSApple OSS Distributions 26*0f4c859eSApple OSS DistributionsThis document will present the best practices to allocate memory 27*0f4c859eSApple OSS Distributionsin the kernel, from a security perspective. 28*0f4c859eSApple OSS Distributions 29*0f4c859eSApple OSS Distributions## Permanent allocations 30*0f4c859eSApple OSS Distributions 31*0f4c859eSApple OSS DistributionsThe kernel sometimes needs to provide persistent allocations that depend on 32*0f4c859eSApple OSS Distributionsparameters that aren't compile time constants, but will not vary over time (NCPU 33*0f4c859eSApple OSS Distributionsis an obvious example here). 34*0f4c859eSApple OSS Distributions 35*0f4c859eSApple OSS DistributionsThe zone subsystem provides a `zalloc_permanent*` family of functions that help 36*0f4c859eSApple OSS Distributionsallocating memory in such a fashion in a very compact way. 37*0f4c859eSApple OSS Distributions 38*0f4c859eSApple OSS DistributionsUnlike the typical zone allocators, this allows for arbitrary sizes, in a 39*0f4c859eSApple OSS Distributionssimilar fashion to `kalloc`. These functions will never fail (if the allocation 40*0f4c859eSApple OSS Distributionsfails, the kernel will panic), and always return zeroed memory. Trying to free 41*0f4c859eSApple OSS Distributionsthese allocations results in a kernel panic. 42*0f4c859eSApple OSS Distributions 43*0f4c859eSApple OSS Distributions## Allocation flags 44*0f4c859eSApple OSS Distributions 45*0f4c859eSApple OSS DistributionsMost `zalloc` or `kalloc` functions take `zalloc_flags_t` typed flags. 46*0f4c859eSApple OSS DistributionsWhen flags are expected, exactly one of `Z_WAITOK`, `Z_NOWAIT` or `Z_NOPAGEWAIT` 47*0f4c859eSApple OSS Distributionsis to be passed: 48*0f4c859eSApple OSS Distributions 49*0f4c859eSApple OSS Distributions- `Z_WAITOK` means that the zone allocator can wait and block, 50*0f4c859eSApple OSS Distributions- `Z_NOWAIT` can be used to require a fully non blocking behavior, which can be 51*0f4c859eSApple OSS Distributions used for allocations under spinlock and other preemption disabled contexts; 52*0f4c859eSApple OSS Distributions- `Z_NOPAGEWAIT` allows for the allocator to block (typically on mutexes), 53*0f4c859eSApple OSS Distributions but not to wait for available pages if there are none, this is only useful 54*0f4c859eSApple OSS Distributions for the buffer cache, and most client should either use `Z_NOWAIT` or `Z_WAITOK`. 55*0f4c859eSApple OSS Distributions 56*0f4c859eSApple OSS DistributionsOther important flags: 57*0f4c859eSApple OSS Distributions 58*0f4c859eSApple OSS Distributions- `Z_ZERO` if zeroed memory is expected (nowadays most of the allocations will 59*0f4c859eSApple OSS Distributions be zeroed regardless, but it's always clearer to specify it), note that it is 60*0f4c859eSApple OSS Distributions often more efficient than calling bzero as the allocator tends to maintain 61*0f4c859eSApple OSS Distributions freed memory as zeroed in the first place, 62*0f4c859eSApple OSS Distributions- `Z_NOFAIL` if the caller knows the allocation can't fail: allocations that are 63*0f4c859eSApple OSS Distributions made with `Z_WAITOK` from regular (non exhaustible) zones, or from `kalloc*` 64*0f4c859eSApple OSS Distributions interfaces with a size smaller than `KALLOC_SAFE_ALLOC_SIZE`, 65*0f4c859eSApple OSS Distributions will never fail (the kernel will instead panic if no memory can be found). 66*0f4c859eSApple OSS Distributions `Z_NOFAIL` can be used to denote that the caller knows about this. 67*0f4c859eSApple OSS Distributions If `Z_NOFAIL` is incorrectly used, then the zone allocator will panic at runtime. 68*0f4c859eSApple OSS Distributions 69*0f4c859eSApple OSS Distributions## Zones (`zalloc`) 70*0f4c859eSApple OSS Distributions 71*0f4c859eSApple OSS DistributionsThe first blessed way to allocate memory in the kernel is by using zones. 72*0f4c859eSApple OSS DistributionsZones are mostly meant to be used in Core XNU and some "BSD" kexts. 73*0f4c859eSApple OSS Distributions 74*0f4c859eSApple OSS DistributionsIt is generally recommended to create zones early and to store the `zone_t` 75*0f4c859eSApple OSS Distributionspointer in read-only memory (using `SECURITY_READ_ONLY_LATE` storage). 76*0f4c859eSApple OSS Distributions 77*0f4c859eSApple OSS DistributionsZones are more feature-rich than `kalloc`, and some features can only be 78*0f4c859eSApple OSS Distributionsused when making a zone: 79*0f4c859eSApple OSS Distributions 80*0f4c859eSApple OSS Distributions- the object type being allocated requires extremely strong segregation 81*0f4c859eSApple OSS Distributions from other types (typically `zone_require` will be used with this zone), 82*0f4c859eSApple OSS Distributions- the object type implements some form of security boundary and wants to adopt 83*0f4c859eSApple OSS Distributions the read-only allocator (See `ZC_READONLY`), 84*0f4c859eSApple OSS Distributions- the allocation must be per-cpu, 85*0f4c859eSApple OSS Distributions- ... 86*0f4c859eSApple OSS Distributions 87*0f4c859eSApple OSS DistributionsIn the vast majority of cases however, using `kalloc_type` (or `IOMallocType`) 88*0f4c859eSApple OSS Distributionsis preferred. 89*0f4c859eSApple OSS Distributions 90*0f4c859eSApple OSS Distributions 91*0f4c859eSApple OSS Distributions## The Typed allocator 92*0f4c859eSApple OSS Distributions 93*0f4c859eSApple OSS DistributionsIgnoring VM allocations (or wrappers like `IOMemoryDescriptor`), the only 94*0f4c859eSApple OSS Distributionsblessed way to allocate typed memory in XNU is using the typed allocator 95*0f4c859eSApple OSS Distributions`kalloc_type` or one of its variants (like IOKit's `IOMallocType`) and untyped 96*0f4c859eSApple OSS Distributionsmemory that doesn't contain pointers is using the data API `kalloc_data` or 97*0f4c859eSApple OSS Distributionsone of its variants (like IOKit's `IOMallocData`). However, this comes with 98*0f4c859eSApple OSS Distributionsadditional requirements. 99*0f4c859eSApple OSS Distributions 100*0f4c859eSApple OSS DistributionsNote that at this time, those interfaces aren't exported to third parties, 101*0f4c859eSApple OSS Distributionsas its ABI has not yet converged. 102*0f4c859eSApple OSS Distributions 103*0f4c859eSApple OSS Distributions### A word about types 104*0f4c859eSApple OSS Distributions 105*0f4c859eSApple OSS DistributionsThe typed allocators assume that allocated types fit a very precise model. 106*0f4c859eSApple OSS DistributionsIf the allocations you perform do not fit the model, then your types 107*0f4c859eSApple OSS Distributionsmust be restructured to fit, for security reasons. 108*0f4c859eSApple OSS Distributions 109*0f4c859eSApple OSS DistributionsA general theme will be the separation of data/primitive types from pointers, 110*0f4c859eSApple OSS Distributionsas attackers tend to use data/pointer overlaps to carry out their exploitations. 111*0f4c859eSApple OSS Distributions 112*0f4c859eSApple OSS DistributionsThe typed allocators use compiler support to infer signatures 113*0f4c859eSApple OSS Distributionsof the types being allocated. Because some scalars actually represent 114*0f4c859eSApple OSS Distributionskernel pointers (like `vm_offset_t`,`vm_address_t`, `uintptr_t`, ...), 115*0f4c859eSApple OSS Distributionstypes or structure members can be decorated with `__kernel_ptr_semantics` 116*0f4c859eSApple OSS Distributionsto denote when a data-looking type is actually a pointer. 117*0f4c859eSApple OSS Distributions 118*0f4c859eSApple OSS DistributionsDo note that `__kernel_data_semantics` and `__kernel_dual_semantics` 119*0f4c859eSApple OSS Distributionsare also provided but should typically rarely be used. 120*0f4c859eSApple OSS Distributions 121*0f4c859eSApple OSS Distributions#### fixed-sized types 122*0f4c859eSApple OSS Distributions 123*0f4c859eSApple OSS DistributionsThe first case is fixed size types, this is typically a `struct`, `union` 124*0f4c859eSApple OSS Distributionsor C++ `class`. Fixed-size types must follow certain rules: 125*0f4c859eSApple OSS Distributions 126*0f4c859eSApple OSS Distributions- types should be small enough to fit in the zone allocator: 127*0f4c859eSApple OSS Distributions smaller than `KALLOC_SAFE_ALLOC_SIZE`. When this is not the case, 128*0f4c859eSApple OSS Distributions we have typically found that there is a large array of data, 129*0f4c859eSApple OSS Distributions or some buffer in that type, the solution is to outline this allocation. 130*0f4c859eSApple OSS Distributions- for union types, data/pointer overlaps should be avoided if possible. 131*0f4c859eSApple OSS Distributions when this isn't possible, a zone should be considered. 132*0f4c859eSApple OSS Distributions 133*0f4c859eSApple OSS Distributions#### Variable-sized types 134*0f4c859eSApple OSS Distributions 135*0f4c859eSApple OSS DistributionsThese come in two variants: arrays, and arrays prefixed with a header. 136*0f4c859eSApple OSS DistributionsAny other case must be reduced to those, by possibly making more allocations. 137*0f4c859eSApple OSS Distributions 138*0f4c859eSApple OSS DistributionsAn array is simply an allocation of several fixed-size types, 139*0f4c859eSApple OSS Distributionsand the rules of "fixed-sized types" above apply to them. 140*0f4c859eSApple OSS Distributions 141*0f4c859eSApple OSS DistributionsThe following rules are expected when dealing with variable sized allocations: 142*0f4c859eSApple OSS Distributions 143*0f4c859eSApple OSS Distributions- variable sized allocations should have a single owner and not be refcounted; 144*0f4c859eSApple OSS Distributions- under the header-prefixed form, if the header contains pointers, 145*0f4c859eSApple OSS Distributions then the array element type **must not** be only data. 146*0f4c859eSApple OSS Distributions 147*0f4c859eSApple OSS DistributionsIf those rules can't be followed, then the allocation must be split with 148*0f4c859eSApple OSS Distributionsthe header becoming a fixed-sized type becoming the single owner 149*0f4c859eSApple OSS Distributionsof an array. 150*0f4c859eSApple OSS Distributions 151*0f4c859eSApple OSS Distributions#### Untyped memory 152*0f4c859eSApple OSS Distributions 153*0f4c859eSApple OSS DistributionsWhen allocating untyped memory with the data APIs ensure that it doesn't 154*0f4c859eSApple OSS Distributionscontain kernel pointers. If your untyped allocation contains kernel pointers 155*0f4c859eSApple OSS Distributionsconsider splitting the allocation into two: one part that is typed and contains 156*0f4c859eSApple OSS Distributionsthe kernel pointers and the second that is untyped and data-only. 157*0f4c859eSApple OSS Distributions 158*0f4c859eSApple OSS Distributions### API surface 159*0f4c859eSApple OSS Distributions 160*0f4c859eSApple OSS Distributions<table> 161*0f4c859eSApple OSS Distributions <tr> 162*0f4c859eSApple OSS Distributions <th>Interface</th> 163*0f4c859eSApple OSS Distributions <th>API</th> 164*0f4c859eSApple OSS Distributions <th>Notes</th> 165*0f4c859eSApple OSS Distributions </tr> 166*0f4c859eSApple OSS Distributions <tr> 167*0f4c859eSApple OSS Distributions <td>Data/Primitive types</td> 168*0f4c859eSApple OSS Distributions <td> 169*0f4c859eSApple OSS Distributions <p> 170*0f4c859eSApple OSS Distributions <b>Core Kernel</b>:<br/> 171*0f4c859eSApple OSS Distributions <tt>kalloc_data(size, flags)</tt><br/> 172*0f4c859eSApple OSS Distributions <tt>krealloc_data(ptr, old_size, new_size, flags)</tt><br/> 173*0f4c859eSApple OSS Distributions <tt>kfree_data(ptr, size)</tt><br/> 174*0f4c859eSApple OSS Distributions <tt>kfree_data_addr(ptr)</tt> 175*0f4c859eSApple OSS Distributions </p> 176*0f4c859eSApple OSS Distributions <p> 177*0f4c859eSApple OSS Distributions <b>IOKit untyped variant (returns <tt>void *</tt>)</b>:<br/> 178*0f4c859eSApple OSS Distributions <tt>IOMallocData(size)</tt><br/> 179*0f4c859eSApple OSS Distributions <tt>IOMallocZeroData(size)</tt><br/> 180*0f4c859eSApple OSS Distributions <tt>IOFreeData(ptr, size)</tt> 181*0f4c859eSApple OSS Distributions </p> 182*0f4c859eSApple OSS Distributions <p> 183*0f4c859eSApple OSS Distributions <b>IOKit typed variant (returns <tt>type_t *</tt>)</b>:<br/> 184*0f4c859eSApple OSS Distributions <tt>IONewData(type_t, count)</tt><br/> 185*0f4c859eSApple OSS Distributions <tt>IONewZeroData(type_t, count)</tt><br/> 186*0f4c859eSApple OSS Distributions <tt>IODeleteData(ptr, type_t, count)</tt> 187*0f4c859eSApple OSS Distributions </p> 188*0f4c859eSApple OSS Distributions </td> 189*0f4c859eSApple OSS Distributions <td>This should be used when the allocated type contains no kernel pointer only</td> 190*0f4c859eSApple OSS Distributions </tr> 191*0f4c859eSApple OSS Distributions <tr> 192*0f4c859eSApple OSS Distributions <td>Fixed-sized type</td> 193*0f4c859eSApple OSS Distributions <td> 194*0f4c859eSApple OSS Distributions <p> 195*0f4c859eSApple OSS Distributions <b>Core Kernel</b>:<br/> 196*0f4c859eSApple OSS Distributions <tt>kalloc_type(type_t, flags)</tt><br/> 197*0f4c859eSApple OSS Distributions <tt>kfree_type(type_t, ptr)</tt> 198*0f4c859eSApple OSS Distributions </p> 199*0f4c859eSApple OSS Distributions <p> 200*0f4c859eSApple OSS Distributions <b>IOKit:</b><br/> 201*0f4c859eSApple OSS Distributions <tt>IOMallocType(type_t)</tt><br/> 202*0f4c859eSApple OSS Distributions <tt>IOFreeType(ptr, type_t)</tt> 203*0f4c859eSApple OSS Distributions </p> 204*0f4c859eSApple OSS Distributions </td> 205*0f4c859eSApple OSS Distributions <td> 206*0f4c859eSApple OSS Distributions <p> 207*0f4c859eSApple OSS Distributions Note that this is absolutely OK to use this variant 208*0f4c859eSApple OSS Distributions for data/primitive types, it will be redirected to <tt>kalloc_data</tt> 209*0f4c859eSApple OSS Distributions (or <tt>IOMallocData</tt>). 210*0f4c859eSApple OSS Distributions </p> 211*0f4c859eSApple OSS Distributions </td> 212*0f4c859eSApple OSS Distributions </tr> 213*0f4c859eSApple OSS Distributions <tr> 214*0f4c859eSApple OSS Distributions <td>Arrays of fixed-sized type</td> 215*0f4c859eSApple OSS Distributions <td> 216*0f4c859eSApple OSS Distributions <p> 217*0f4c859eSApple OSS Distributions <b>Core Kernel</b>:<br/> 218*0f4c859eSApple OSS Distributions <tt>kalloc_type(type_t, count, flags)</tt><br/> 219*0f4c859eSApple OSS Distributions <tt>kfree_type(type_t, count, ptr)</tt> 220*0f4c859eSApple OSS Distributions </p> 221*0f4c859eSApple OSS Distributions <p> 222*0f4c859eSApple OSS Distributions <b>IOKit:</b><br/> 223*0f4c859eSApple OSS Distributions <tt>IONew(type_t, count)</tt><br/> 224*0f4c859eSApple OSS Distributions <tt>IONewZero(type_t, count)</tt><br/> 225*0f4c859eSApple OSS Distributions <tt>IODelete(ptr, type_t, count)</tt> 226*0f4c859eSApple OSS Distributions </p> 227*0f4c859eSApple OSS Distributions </td> 228*0f4c859eSApple OSS Distributions <td> 229*0f4c859eSApple OSS Distributions <p> 230*0f4c859eSApple OSS Distributions <tt>kalloc_type(type_t, ...)</tt> (resp. <tt>IONew(type_t, 1)</tt>) 231*0f4c859eSApple OSS Distributions <b>isn't</b> equivalent to <tt>kalloc_type(type_t, 1, ...)</tt> 232*0f4c859eSApple OSS Distributions (resp. <tt>IOMallocType(type_t)</tt>). Mix-and-matching interfaces 233*0f4c859eSApple OSS Distributions will result in panics. 234*0f4c859eSApple OSS Distributions </p> 235*0f4c859eSApple OSS Distributions <p> 236*0f4c859eSApple OSS Distributions Note that this is absolutely OK to use this variant 237*0f4c859eSApple OSS Distributions for data/primitive types, it will be redirected to <tt>kalloc_data</tt>. 238*0f4c859eSApple OSS Distributions </p> 239*0f4c859eSApple OSS Distributions </td> 240*0f4c859eSApple OSS Distributions </tr> 241*0f4c859eSApple OSS Distributions <tr> 242*0f4c859eSApple OSS Distributions <td>Header-prefixed arrays of fixed-sized type</td> 243*0f4c859eSApple OSS Distributions <td> 244*0f4c859eSApple OSS Distributions <p> 245*0f4c859eSApple OSS Distributions <b>Core Kernel</b>:<br/> 246*0f4c859eSApple OSS Distributions <tt>kalloc_type(hdr_type_t, type_t, count, flags)</tt><br/> 247*0f4c859eSApple OSS Distributions <tt>kfree_type(hdr_type_t, type_t, count, ptr)</tt> 248*0f4c859eSApple OSS Distributions </p> 249*0f4c859eSApple OSS Distributions <p> 250*0f4c859eSApple OSS Distributions <b>IOKit:</b><br/> 251*0f4c859eSApple OSS Distributions <tt>IONew(hdr_type_t, type_t, count)</tt><br/> 252*0f4c859eSApple OSS Distributions <tt>IONewZero(hdr_type_t, type_t, count)</tt><br/> 253*0f4c859eSApple OSS Distributions <tt>IODelete(ptr, hdr_type_t, type_t, count)</tt> 254*0f4c859eSApple OSS Distributions </p> 255*0f4c859eSApple OSS Distributions </td> 256*0f4c859eSApple OSS Distributions <td> 257*0f4c859eSApple OSS Distributions <p> 258*0f4c859eSApple OSS Distributions <tt>hdr_type_t</tt> can't contain a refcount, 259*0f4c859eSApple OSS Distributions and <tt>type_t</tt> can't be a primitive type. 260*0f4c859eSApple OSS Distributions </p> 261*0f4c859eSApple OSS Distributions </td> 262*0f4c859eSApple OSS Distributions </tr> 263*0f4c859eSApple OSS Distributions</table> 264*0f4c859eSApple OSS Distributions 265*0f4c859eSApple OSS Distributions## C++ classes and operator new. 266*0f4c859eSApple OSS Distributions 267*0f4c859eSApple OSS DistributionsThis section covers how typed allocators should be adopted to use 268*0f4c859eSApple OSS Distributions`operator new/delete` in C++. For C++ classes, the approach required 269*0f4c859eSApple OSS Distributionsdiffers based on whether the class inherits from `OSObject` or not. 270*0f4c859eSApple OSS Distributions 271*0f4c859eSApple OSS DistributionsMost, if not all, C++ objects used in conjuction with IOKit APIs 272*0f4c859eSApple OSS Distributionsshould probably use OSObject as a base class. C++ operators 273*0f4c859eSApple OSS Distributionsand non-POD types should be used seldomly. 274*0f4c859eSApple OSS Distributions 275*0f4c859eSApple OSS Distributions### `OSObject` subclasses 276*0f4c859eSApple OSS Distributions 277*0f4c859eSApple OSS DistributionsAll subclasses of `OSObject` must declare and define one of IOKit's 278*0f4c859eSApple OSS Distributions`OSDeclare*` and `OSDefine*` macros. As part of those, an `operator new` and 279*0f4c859eSApple OSS Distributions`operator delete` are injected that force objects to enroll into `kalloc_type`. 280*0f4c859eSApple OSS Distributions 281*0f4c859eSApple OSS DistributionsNote that idiomatic IOKit is supposed to use `OSTypeAlloc(Class)`. 282*0f4c859eSApple OSS Distributions 283*0f4c859eSApple OSS Distributions### Other classes 284*0f4c859eSApple OSS Distributions 285*0f4c859eSApple OSS DistributionsUnlike `OSObject` subclasses, regular C++ classes must adopt typed allocators 286*0f4c859eSApple OSS Distributionsmanually. If your struct or class is POD (Plain Old Data), then replacing usage of 287*0f4c859eSApple OSS Distributions`new/delete` (resp. `new[]/delete[]`) with `IOMallocType/IOFreeType` (resp. 288*0f4c859eSApple OSS Distributions`IONew/IODelete`) is safe. 289*0f4c859eSApple OSS Distributions 290*0f4c859eSApple OSS DistributionsHowever, if you have non default structors, or members of your class/struct 291*0f4c859eSApple OSS Distributionshave non default structors, you will need to manually enroll it into `kalloc_type`. 292*0f4c859eSApple OSS DistributionsThis can be accomplished through one of the following approaches, and it lets you 293*0f4c859eSApple OSS Distributionsto continue to use C++'s new and delete keywords to allocate/deallocate instances. 294*0f4c859eSApple OSS Distributions 295*0f4c859eSApple OSS DistributionsThe first approach is to subclass the IOTypedOperatorsMixin struct. This will 296*0f4c859eSApple OSS Distributionsadopt typed allocators for your class/struct by providing the appropriate 297*0f4c859eSApple OSS Distributionsimplementations for `operator new/delete`: 298*0f4c859eSApple OSS Distributions 299*0f4c859eSApple OSS Distributions```cpp 300*0f4c859eSApple OSS Distributionsstruct Type : public IOTypedOperatorsMixin<Type> { 301*0f4c859eSApple OSS Distributions ... 302*0f4c859eSApple OSS Distributions}; 303*0f4c859eSApple OSS Distributions``` 304*0f4c859eSApple OSS Distributions 305*0f4c859eSApple OSS DistributionsAlternatively, if you cannot use the mixin approach, you can use the 306*0f4c859eSApple OSS Distributions`IOOverrideTypedOperators` macro to override `operator new/delete` 307*0f4c859eSApple OSS Distributionswithin your class/struct declaration: 308*0f4c859eSApple OSS Distributions 309*0f4c859eSApple OSS Distributions```cpp 310*0f4c859eSApple OSS Distributionsstruct Type { 311*0f4c859eSApple OSS Distributions IOOverrideTypedOperators(Type); 312*0f4c859eSApple OSS Distributions ... 313*0f4c859eSApple OSS Distributions}; 314*0f4c859eSApple OSS Distributions``` 315*0f4c859eSApple OSS Distributions 316*0f4c859eSApple OSS DistributionsFinally, if you need to decouple the declaration of the operators from 317*0f4c859eSApple OSS Distributionstheir implementation, you can use `IODeclareTypedOperators` paired with 318*0f4c859eSApple OSS Distributions`IODefineTypedOperators`, to declare the operators within your class/struct 319*0f4c859eSApple OSS Distributionsdeclaration and then provide their definition out of line: 320*0f4c859eSApple OSS Distributions 321*0f4c859eSApple OSS Distributions```cpp 322*0f4c859eSApple OSS Distributions// declaration 323*0f4c859eSApple OSS Distributionsstruct Type { 324*0f4c859eSApple OSS Distributions IODeclareTypedOperators(Type); 325*0f4c859eSApple OSS Distributions ... 326*0f4c859eSApple OSS Distributions}; 327*0f4c859eSApple OSS Distributions 328*0f4c859eSApple OSS Distributions// definition 329*0f4c859eSApple OSS DistributionsIODefineTypedOperators(Type) 330*0f4c859eSApple OSS Distributions``` 331*0f4c859eSApple OSS Distributions 332*0f4c859eSApple OSS DistributionsWhen a class/struct adopts typed allocators through one of those approaches, 333*0f4c859eSApple OSS Distributionsall its subclasses must also explicitly adopt typed allocators. It is not 334*0f4c859eSApple OSS Distributionssufficient for a common parent within the class hierarchy to enroll, in order to 335*0f4c859eSApple OSS Distributionsautomatically provide the implementation of the operators for all of its children: 336*0f4c859eSApple OSS Distributionseach and every subclass in the class hierarchy must also explicitly do the same. 337*0f4c859eSApple OSS Distributions 338*0f4c859eSApple OSS Distributions### The case of `operator new[]` 339*0f4c859eSApple OSS Distributions 340*0f4c859eSApple OSS DistributionsThe ABI of `operator new[]` is unfortunate, as it denormalizes 341*0f4c859eSApple OSS Distributionsdata that we prefer to be known by the owning object 342*0f4c859eSApple OSS Distributions(the element sizes and array element count). 343*0f4c859eSApple OSS Distributions 344*0f4c859eSApple OSS DistributionsIt also makes those allocations ripe for abuse in an adversarial 345*0f4c859eSApple OSS Distributionscontext as this denormalized information is at the begining 346*0f4c859eSApple OSS Distributionsof the structure, making it relatively easy to attack with 347*0f4c859eSApple OSS Distributionsout-of-bounds bugs. 348*0f4c859eSApple OSS Distributions 349*0f4c859eSApple OSS DistributionsFor this reason, the default variants of the mixin and the macros 350*0f4c859eSApple OSS Distributionspresented above will delete the implementation of `operator new[]` 351*0f4c859eSApple OSS Distributionsfrom the class they are applied to. 352*0f4c859eSApple OSS Distributions 353*0f4c859eSApple OSS DistributionsHowever, if those must be used, you can add adopt the typed 354*0f4c859eSApple OSS Distributionsallocators on your class by using the appropriate variant 355*0f4c859eSApple OSS Distributionswhich explicitly implements the support for array operators: 356*0f4c859eSApple OSS Distributions- `IOTypedOperatorsMixinSupportingArrayOperators` 357*0f4c859eSApple OSS Distributions- `IOOverrideTypedOperatorsSupportingArrayOperators` 358*0f4c859eSApple OSS Distributions- `IO{Declare, Define}TypedOperatorsSupportingArrayOperators` 359*0f4c859eSApple OSS Distributions 360*0f4c859eSApple OSS Distributions### Scalar types 361*0f4c859eSApple OSS Distributions 362*0f4c859eSApple OSS DistributionsThe only accepted ways of using `operator new/delete` and their variants are the ones 363*0f4c859eSApple OSS Distributionsdescribed above. You should never use the operators on scalar types. Instead, you 364*0f4c859eSApple OSS Distributionsshould use the appropriate typed allocator API based on the semantics of the memory 365*0f4c859eSApple OSS Distributionsbeing allocated (i.e. `IOMallocData` for data only buffers, and `IOMallocType`/`IONew` 366*0f4c859eSApple OSS Distributionsfor any other type). 367*0f4c859eSApple OSS Distributions 368*0f4c859eSApple OSS Distributions### Wrapping C++ type allocation in container OSObjects 369*0f4c859eSApple OSS DistributionsThe blessed way of wrapping and passing a C++ type allocation for use in the 370*0f4c859eSApple OSS Distributionslibkern collection is using `OSValueObject`. Please do no use OSData for this 371*0f4c859eSApple OSS Distributionspurpose as its backing store should not contain kernel pointers. 372*0f4c859eSApple OSS Distributions 373