/ duct-tape / xnu / osfmk / kern / kalloc.h
kalloc.h
  1  /*
  2   * Copyright (c) 2000-2020 Apple Computer, Inc. All rights reserved.
  3   *
  4   * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  5   *
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. The rights granted to you under the License
 10   * may not be used to create, or enable the creation or redistribution of,
 11   * unlawful or unlicensed copies of an Apple operating system, or to
 12   * circumvent, violate, or enable the circumvention or violation of, any
 13   * terms of an Apple operating system software license agreement.
 14   *
 15   * Please obtain a copy of the License at
 16   * http://www.opensource.apple.com/apsl/ and read it before using this file.
 17   *
 18   * The Original Code and all software distributed under the License are
 19   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 20   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 21   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 22   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 23   * Please see the License for the specific language governing rights and
 24   * limitations under the License.
 25   *
 26   * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 27   */
 28  /*
 29   * @OSF_COPYRIGHT@
 30   */
 31  /*
 32   * Mach Operating System
 33   * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
 34   * All Rights Reserved.
 35   *
 36   * Permission to use, copy, modify and distribute this software and its
 37   * documentation is hereby granted, provided that both the copyright
 38   * notice and this permission notice appear in all copies of the
 39   * software, derivative works or modified versions, and any portions
 40   * thereof, and that both notices appear in supporting documentation.
 41   *
 42   * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 43   * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 44   * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 45   *
 46   * Carnegie Mellon requests users of this software to return to
 47   *
 48   *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 49   *  School of Computer Science
 50   *  Carnegie Mellon University
 51   *  Pittsburgh PA 15213-3890
 52   *
 53   * any improvements or extensions that they make and grant Carnegie Mellon
 54   * the rights to redistribute these changes.
 55   */
 56  
 57  #ifdef  KERNEL_PRIVATE
 58  
 59  #ifndef _KERN_KALLOC_H_
 60  #define _KERN_KALLOC_H_
 61  
 62  #include <mach/machine/vm_types.h>
 63  #include <mach/boolean.h>
 64  #include <mach/vm_types.h>
 65  #include <kern/zalloc.h>
 66  
 67  __BEGIN_DECLS
 68  
 69  #if XNU_KERNEL_PRIVATE
 70  
 71  /*!
 72   * @typedef kalloc_heap_t
 73   *
 74   * @abstract
 75   * A kalloc heap view represents a sub-accounting context
 76   * for a given kalloc heap.
 77   */
 78  typedef struct kalloc_heap {
 79  	struct kheap_zones *kh_zones;
 80  	zone_stats_t        kh_stats;
 81  	const char         *kh_name;
 82  	struct kalloc_heap *kh_next;
 83  	zone_kheap_id_t     kh_heap_id;
 84  } *kalloc_heap_t;
 85  
 86  /*!
 87   * @macro KALLOC_HEAP_DECLARE
 88   *
 89   * @abstract
 90   * (optionally) declare a kalloc heap view in a header.
 91   *
 92   * @discussion
 93   * Unlike kernel zones, new full blown heaps cannot be instantiated.
 94   * However new accounting views of the base heaps can be made.
 95   */
 96  #define KALLOC_HEAP_DECLARE(var) \
 97  	extern struct kalloc_heap var[1]
 98  
 99  /**
100   * @const KHEAP_ANY
101   *
102   * @brief
103   * A value that represents either the default or kext heap for codepaths that
104   * need to allow @c kheap_free() to either one.
105   *
106   * @discussion
107   * When the memory provenance is not known, this value can be used to free
108   * memory indiscriminately.
109   *
110   * Note: code using this constant can likely be used as a gadget to free
111   * arbitrary memory and its use is strongly discouraged.
112   */
113  #define KHEAP_ANY  ((struct kalloc_heap *)NULL)
114  
115  /**
116   * @const KHEAP_DATA_BUFFERS
117   *
118   * @brief
119   * The builtin heap for bags of pure bytes.
120   *
121   * @discussion
122   * This set of kalloc zones should contain pure bags of bytes with no pointers
123   * or length/offset fields.
124   *
125   * The zones forming the heap aren't sequestered from each other, however the
126   * entire heap lives in a different submap from any other kernel allocation.
127   *
128   * The main motivation behind this separation is due to the fact that a lot of
129   * these objects have been used by attackers to spray the heap to make it more
130   * predictable while exploiting use-after-frees or overflows.
131   *
132   * Common attributes that make these objects useful for spraying includes
133   * control of:
134   * - Data in allocation
135   * - Time of alloc and free (lifetime)
136   * - Size of allocation
137   */
138  KALLOC_HEAP_DECLARE(KHEAP_DATA_BUFFERS);
139  
140  /**
141   * @const KHEAP_KEXT
142   *
143   * @brief
144   * The builtin heap for allocations made by kexts.
145   *
146   * @discussion
147   * This set of kalloc zones should contain allocations from kexts and the
148   * individual zones in this heap are sequestered.
149   */
150  KALLOC_HEAP_DECLARE(KHEAP_KEXT);
151  
152  /**
153   * @const KHEAP_DEFAULT
154   *
155   * @brief
156   * The builtin default core kernel kalloc heap.
157   *
158   * @discussion
159   * This set of kalloc zones should contain other objects that don't have their
160   * own security mitigations. The individual zones are themselves sequestered.
161   */
162  KALLOC_HEAP_DECLARE(KHEAP_DEFAULT);
163  
164  /**
165   * @const KHEAP_TEMP
166   *
167   * @brief
168   * A heap that represents allocations that are always done in "scope" of
169   * a thread.
170   *
171   * @discussion
172   * Allocations in this heap must be allocated and freed "in scope", which means:
173   * - the thread that did the allocation will be the one doing the free,
174   * - allocations will be freed by the time the thread returns to userspace.
175   *
176   * This is an alias on the @c KHEAP_DEFAULT heap with added checks.
177   */
178  KALLOC_HEAP_DECLARE(KHEAP_TEMP);
179  
180  /*!
181   * @macro KALLOC_HEAP_DEFINE
182   *
183   * @abstract
184   * Defines a given kalloc heap view and what it points to.
185   *
186   * @discussion
187   * Kalloc heaps are views over one of the pre-defined builtin heaps
188   * (such as @c KHEAP_DATA_BUFFERS or @c KHEAP_DEFAULT). Instantiating
189   * a new one allows for accounting of allocations through this view.
190   *
191   * Kalloc heap views are initialized during the @c STARTUP_SUB_ZALLOC phase,
192   * as the last rank. If views on zones are created, these must have been
193   * created before this stage.
194   *
195   * @param var           the name for the zone view.
196   * @param name          a string describing the zone view.
197   * @param heap_id       a @c KHEAP_ID_* constant.
198   */
199  #define KALLOC_HEAP_DEFINE(var, name, heap_id) \
200  	SECURITY_READ_ONLY_LATE(struct kalloc_heap) var[1] = { { \
201  	    .kh_name = name, \
202  	    .kh_heap_id = heap_id, \
203  	} }; \
204  	STARTUP_ARG(ZALLOC, STARTUP_RANK_LAST, kheap_startup_init, var)
205  
206  #define kalloc(size) \
207  	kheap_alloc(KHEAP_DEFAULT, size, Z_WAITOK)
208  
209  #define kalloc_flags(size, flags) \
210  	kheap_alloc(KHEAP_DEFAULT, size, flags)
211  
212  #define kalloc_tag(size, itag) \
213  	kheap_alloc_tag(KHEAP_DEFAULT, size, Z_WAITOK, itag)
214  
215  #define kalloc_tag_bt(size, itag) \
216  	kheap_alloc_tag_bt(KHEAP_DEFAULT, size, Z_WAITOK, itag)
217  
218  #define krealloc(elem, old_size, new_size, flags) \
219  	kheap_realloc(KHEAP_DEFAULT, elem, old_size, new_size, flags)
220  
221  /*
222   * These versions allow specifying the kalloc heap to allocate memory
223   * from
224   */
225  #define kheap_alloc(kalloc_heap, size, flags)                           \
226  	({ VM_ALLOC_SITE_STATIC(0, 0);                                  \
227  	kalloc_ext(kalloc_heap, size, flags, &site).addr; })
228  
229  #define kheap_alloc_tag(kalloc_heap, size, flags, itag)                 \
230  	({ VM_ALLOC_SITE_STATIC(0, (itag));                             \
231  	kalloc_ext(kalloc_heap, size, flags, &site).addr; })
232  
233  #define kheap_alloc_tag_bt(kalloc_heap, size, flags, itag)              \
234  	({ VM_ALLOC_SITE_STATIC(VM_TAG_BT, (itag));                     \
235  	kalloc_ext(kalloc_heap, size, flags, &site).addr; })
236  
237  #define kheap_realloc(kalloc_heap, elem, old_size, new_size, flags)     \
238  	({ VM_ALLOC_SITE_STATIC(0, 0);                                  \
239  	krealloc_ext(kalloc_heap, elem, old_size, new_size, flags, &site).addr; })
240  
241  extern void
242  kfree(
243  	void         *data,
244  	vm_size_t     size);
245  
246  extern void
247  kheap_free(
248  	kalloc_heap_t heap,
249  	void         *data,
250  	vm_size_t     size);
251  
252  __abortlike
253  extern void
254  kheap_temp_leak_panic(thread_t self);
255  
256  #else /* XNU_KERNEL_PRIVATE */
257  
258  extern void *kalloc(vm_size_t size) __attribute__((alloc_size(1)));
259  
260  extern void  kfree(void *data, vm_size_t size);
261  
262  #endif /* !XNU_KERNEL_PRIVATE */
263  #pragma mark implementation details
264  #if XNU_KERNEL_PRIVATE
265  #pragma GCC visibility push(hidden)
266  
267  /* Used by kern_os_* and operator new */
268  KALLOC_HEAP_DECLARE(KERN_OS_MALLOC);
269  
270  extern void kheap_startup_init(
271  	kalloc_heap_t heap);
272  
273  
274  /*
275   * This type is used so that kalloc_internal has good calling conventions
276   * for callers who want to cheaply both know the allocated address
277   * and the actual size of the allocation.
278   */
279  struct kalloc_result {
280  	void     *addr;
281  	vm_size_t size;
282  };
283  
284  extern struct kalloc_result
285  kalloc_ext(
286  	kalloc_heap_t           kheap,
287  	vm_size_t               size,
288  	zalloc_flags_t          flags,
289  	vm_allocation_site_t   *site);
290  
291  extern struct kalloc_result
292  krealloc_ext(
293  	kalloc_heap_t           kheap,
294  	void                   *addr,
295  	vm_size_t               old_size,
296  	vm_size_t               new_size,
297  	zalloc_flags_t          flags,
298  	vm_allocation_site_t   *site);
299  
300  extern struct kalloc_result
301  kheap_realloc_addr(
302  	kalloc_heap_t           kheap,
303  	void                   *addr,
304  	vm_size_t               new_size,
305  	zalloc_flags_t          flags,
306  	vm_allocation_site_t   *site);
307  
308  
309  /* these versions update the size reference with the actual size allocated */
310  
311  static inline void *
312  kallocp_ext(
313  	kalloc_heap_t           kheap,
314  	vm_size_t              *size,
315  	zalloc_flags_t          flags,
316  	vm_allocation_site_t   *site)
317  {
318  	struct kalloc_result kar = kalloc_ext(kheap, *size, flags, site);
319  	*size = kar.size;
320  	return kar.addr;
321  }
322  
323  #define kallocp(sizep)                                  \
324  	({ VM_ALLOC_SITE_STATIC(0, 0);                  \
325  	kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
326  
327  #define kallocp_tag(sizep, itag)                        \
328  	({ VM_ALLOC_SITE_STATIC(0, (itag));             \
329  	kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
330  
331  #define kallocp_tag_bt(sizep, itag)                     \
332  	({ VM_ALLOC_SITE_STATIC(VM_TAG_BT, (itag));     \
333  	kallocp_ext(KHEAP_DEFAULT, sizep, Z_WAITOK, &site); })
334  
335  extern vm_size_t
336  kalloc_size(
337  	void                 *addr);
338  
339  extern void
340  kheap_free_addr(
341  	kalloc_heap_t         heap,
342  	void                 *addr);
343  
344  extern vm_size_t
345  kalloc_bucket_size(
346  	vm_size_t             size);
347  
348  /*
349   * These macros set "elem" to NULL on free.
350   *
351   * Note: all values passed to k*free() might be in the element to be freed,
352   *       temporaries must be taken, and the resetting to be done prior to free.
353   */
354  #define kfree(elem, size) ({ \
355  	_Static_assert(sizeof(elem) == sizeof(void *), "elem isn't pointer sized"); \
356  	__auto_type __kfree_eptr = &(elem); \
357  	__auto_type __kfree_elem = *__kfree_eptr; \
358  	__auto_type __kfree_size = (size); \
359  	*__kfree_eptr = (__typeof__(__kfree_elem))NULL; \
360  	(kfree)((void *)__kfree_elem, __kfree_size); \
361  })
362  
363  #define kheap_free(heap, elem, size) ({ \
364  	_Static_assert(sizeof(elem) == sizeof(void *), "elem isn't pointer sized"); \
365  	__auto_type __kfree_heap = (heap); \
366  	__auto_type __kfree_eptr = &(elem); \
367  	__auto_type __kfree_elem = *__kfree_eptr; \
368  	__auto_type __kfree_size = (size); \
369  	*__kfree_eptr = (__typeof__(__kfree_elem))NULL; \
370  	(kheap_free)(__kfree_heap, (void *)__kfree_elem, __kfree_size); \
371  })
372  
373  #define kheap_free_addr(heap, elem) ({ \
374  	_Static_assert(sizeof(elem) == sizeof(void *), "elem isn't pointer sized"); \
375  	__auto_type __kfree_heap = (heap); \
376  	__auto_type __kfree_eptr = &(elem); \
377  	__auto_type __kfree_elem = *__kfree_eptr; \
378  	*__kfree_eptr = (__typeof__(__kfree_elem))NULL; \
379  	(kheap_free_addr)(__kfree_heap, (void *)__kfree_elem); \
380  })
381  
382  extern zone_t
383  kalloc_heap_zone_for_size(
384  	kalloc_heap_t             heap,
385  	vm_size_t           size);
386  
387  extern vm_size_t kalloc_max_prerounded;
388  extern vm_size_t kalloc_large_total;
389  
390  extern void
391  kern_os_kfree(
392  	void *addr,
393  	vm_size_t size);
394  
395  #pragma GCC visibility pop
396  #endif  /* XNU_KERNEL_PRIVATE */
397  
398  extern void
399  kern_os_zfree(
400  	zone_t zone,
401  	void *addr,
402  	vm_size_t size);
403  
404  __END_DECLS
405  
406  #endif  /* _KERN_KALLOC_H_ */
407  
408  #endif  /* KERNEL_PRIVATE */