xref: /xnu-11215.81.4/osfmk/vm/vm_sanitize_internal.h (revision d4514f0bc1d3f944c22d92e68b646ac3fb40d452)
1 /*
2  * Copyright (c) 2024 Apple 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 #ifndef _VM_SANITIZE_INTERNAL_H_
30 #define _VM_SANITIZE_INTERNAL_H_
31 
32 #include <mach/vm_types_unsafe.h>
33 #include <mach/error.h>
34 #include <stdbool.h>
35 #include <vm/vm_sanitize_telemetry.h>
36 
37 __BEGIN_DECLS
38 #pragma GCC visibility push(hidden)
39 
40 /*
41  * kern_return_t errors used internally by VM
42  */
43 
44 /*!
45  * @define VM_ERR_RETURN_NOW
46  * @abstract Communicate to a caller that they should
47  * return @c KERN_SUCCESS immediately after completing sanitization checks.
48  */
49 #define VM_ERR_RETURN_NOW (err_vm | err_sub(0) | 1)
50 
51 /*!
52  * @function vm_sanitize_get_kr
53  * @abstract When a VM sanitizer returns an error, use this to extract
54  * the real value that the sanitizers request that you return.
55  *
56  * @discussion errno-returning callers may need to transform this result further
57  *
58  * @param kr                error code set by the sanitizers
59  * @returns                 a (possibly different) error code
60  */
61 static inline
62 kern_return_t
vm_sanitize_get_kr(kern_return_t kr)63 vm_sanitize_get_kr(kern_return_t kr)
64 {
65 	if (kr == VM_ERR_RETURN_NOW) {
66 		return KERN_SUCCESS;
67 	}
68 	return kr;
69 }
70 
71 /*!
72  * @enum vm_sanitize_caller_id_t
73  *
74  * @brief
75  * IDs for callers of sanitization functions that have different
76  * set of return values.
77  */
78 __enum_closed_decl(vm_sanitize_caller_id_t, uint32_t, {
79 	VM_SANITIZE_CALLER_ID_NONE,
80 
81 	/* memory entry */
82 	VM_SANITIZE_CALLER_ID_MACH_MAKE_MEMORY_ENTRY,
83 	VM_SANITIZE_CALLER_ID_MACH_MEMORY_ENTRY_PAGE_OP,
84 	VM_SANITIZE_CALLER_ID_MACH_MEMORY_ENTRY_RANGE_OP,
85 	VM_SANITIZE_CALLER_ID_MACH_MEMORY_ENTRY_MAP_SIZE,
86 	VM_SANITIZE_CALLER_ID_MACH_MEMORY_OBJECT_MEMORY_ENTRY,
87 
88 	/* alloc/dealloc */
89 	VM_SANITIZE_CALLER_ID_VM_ALLOCATE_FIXED,
90 	VM_SANITIZE_CALLER_ID_VM_ALLOCATE_ANYWHERE,
91 	VM_SANITIZE_CALLER_ID_VM_DEALLOCATE,
92 	VM_SANITIZE_CALLER_ID_MUNMAP,
93 
94 	/* map/remap */
95 	VM_SANITIZE_CALLER_ID_VM_MAP_REMAP,
96 	VM_SANITIZE_CALLER_ID_MMAP,
97 	VM_SANITIZE_CALLER_ID_MREMAP_ENCRYPTED,
98 	VM_SANITIZE_CALLER_ID_MAP_WITH_LINKING_NP,
99 	VM_SANITIZE_CALLER_ID_ENTER_MEM_OBJ,
100 	VM_SANITIZE_CALLER_ID_ENTER_MEM_OBJ_CTL,
101 
102 	/* wire/unwire */
103 	VM_SANITIZE_CALLER_ID_VM_WIRE_USER,
104 	VM_SANITIZE_CALLER_ID_VM_UNWIRE_USER,
105 	VM_SANITIZE_CALLER_ID_VM_MAP_WIRE,
106 	VM_SANITIZE_CALLER_ID_VM_MAP_UNWIRE,
107 	VM_SANITIZE_CALLER_ID_VSLOCK,
108 	VM_SANITIZE_CALLER_ID_VSUNLOCK,
109 
110 	/* copyin/copyout */
111 	VM_SANITIZE_CALLER_ID_VM_MAP_COPY_OVERWRITE,
112 	VM_SANITIZE_CALLER_ID_VM_MAP_COPYIN,
113 	VM_SANITIZE_CALLER_ID_VM_MAP_READ_USER,
114 	VM_SANITIZE_CALLER_ID_VM_MAP_WRITE_USER,
115 
116 	/* inherit */
117 	VM_SANITIZE_CALLER_ID_VM_MAP_INHERIT,
118 	VM_SANITIZE_CALLER_ID_MINHERIT,
119 
120 	/* protect */
121 	VM_SANITIZE_CALLER_ID_VM_MAP_PROTECT,
122 	VM_SANITIZE_CALLER_ID_MPROTECT,
123 	VM_SANITIZE_CALLER_ID_USERACC,
124 
125 	/* behavior */
126 	VM_SANITIZE_CALLER_ID_VM_BEHAVIOR_SET,
127 	VM_SANITIZE_CALLER_ID_MADVISE,
128 
129 	/* msync */
130 	VM_SANITIZE_CALLER_ID_VM_MAP_MSYNC,
131 	VM_SANITIZE_CALLER_ID_MSYNC,
132 
133 	/* machine attribute */
134 	VM_SANITIZE_CALLER_ID_VM_MAP_MACHINE_ATTRIBUTE,
135 
136 	/* page info */
137 	VM_SANITIZE_CALLER_ID_VM_MAP_PAGE_RANGE_INFO,
138 	VM_SANITIZE_CALLER_ID_VM_MAP_PAGE_RANGE_QUERY,
139 	VM_SANITIZE_CALLER_ID_MINCORE,
140 
141 	/* single */
142 	VM_SANITIZE_CALLER_ID_MACH_VM_DEFERRED_RECLAMATION_BUFFER_INIT,
143 	VM_SANITIZE_CALLER_ID_MACH_VM_RANGE_CREATE,
144 	VM_SANITIZE_CALLER_ID_SHARED_REGION_MAP_AND_SLIDE_2_NP,
145 
146 	/* test */
147 	VM_SANITIZE_CALLER_ID_TEST
148 });
149 
150 /*!
151  * @enum vm_sanitize_flags_t
152  *
153  * @brief
154  * Flags that influence the sanitization being performed.
155  *
156  * @const VM_SANITIZE_FLAGS_NONE
157  * Default value.
158  *
159  * @const VM_SANITIZE_FLAGS_CHECK_ALIGNED_START
160  * Checks that the start address is aligned to map page size.
161  *
162  * @const VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS
163  * In sanitizers that have a @c size parameter, the sanitizer will ask
164  * the caller to return @c KERN_SUCCESS when @c size @c == @c 0.
165  *
166  * Exactly one of @c VM_SANITIZE_FLAGS_SIZE_ZERO_* must be passed to sanitizers
167  * that return a sanitized size.
168  *
169  * @const VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS
170  * In sanitizers that have a @c size parameter, the sanitizer will ask
171  * the caller to return @c KERN_INVALID_ARGUMENT when @c size @c == @c 0.
172  *
173  * Exactly one of @c VM_SANITIZE_FLAGS_SIZE_ZERO_* must be passed to sanitizers
174  * that return a sanitized size.
175  *
176  * @const VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH
177  * In sanitizers that have a @c size parameter, the sanitizer will not ask
178  * the caller to return when @c size @c == @c 0, thus falling through into
179  * the caller's implementation.
180  *
181  * Exactly one of @c VM_SANITIZE_FLAGS_SIZE_ZERO_* must be passed to sanitizers
182  * that return a sanitized size.
183  *
184  * @const VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES
185  * Return unaligned start/end/size rather than realigned values.
186  *
187  * @const VM_SANITIZE_FLAGS_REALIGN_START
188  * Ignore the misaligned bits of the start address when sanitizing an address.
189  *
190  * @const VM_SANITIZE_FLAGS_CHECK_USER_MEM_MAP_FLAGS
191  * Reject non user allowed mem map flags for memory entry.
192  *
193  * @const VM_SANITIZE_FLAGS_CANONICALIZE
194  * Canonicalize address for CONFIG_KERNEL_TAGGING
195  *
196  * @const VM_SANITIZE_FLAGS_CHECK_ALIGNED_SIZE
197  * Checks that the size is aligned to map page size.
198  *
199  * @const VM_SANITIZE_FLAGS_CHECK_BASE_ADDR_RANGE
200  * Checks that end address is inside the TTBR base address range.
201  */
202 
203 __options_closed_decl(vm_sanitize_flags_t, uint32_t, {
204 	VM_SANITIZE_FLAGS_NONE                     = 0x00000000,
205 	VM_SANITIZE_FLAGS_CHECK_ALIGNED_START      = 0x00000001,
206 	VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS       = 0x00000002,
207 	VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS          = 0x00000004,
208 	VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH    = 0x00000008,
209 	VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES     = 0x00000010,
210 	VM_SANITIZE_FLAGS_REALIGN_START            = 0x00000020,
211 	VM_SANITIZE_FLAGS_CHECK_USER_MEM_MAP_FLAGS = 0x00000040,
212 	VM_SANITIZE_FLAGS_CANONICALIZE             = 0x00000080,
213 	VM_SANITIZE_FLAGS_CHECK_ALIGNED_SIZE       = 0x00000100,
214 	VM_SANITIZE_FLAGS_CHECK_BASE_ADDR_RANGE    = 0x00000200,
215 });
216 
217 #define __vm_sanitize_bits_one_of(flags) \
218 	((flags) != 0 && ((flags) & ((flags) - 1)) == 0)
219 
220 #define __vm_sanitize_assert_one_of(arg, mask) \
221 	__attribute__((diagnose_if(!__vm_sanitize_bits_one_of((arg) & (mask)), \
222 	    "`" #arg "` must have one of these flags `" #mask "`", "error")))
223 
224 #define __vm_sanitize_require_size_zero_flag(arg) \
225 	__vm_sanitize_assert_one_of(arg,          \
226 	    VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS | VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS | VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH)
227 
228 /*
229  * Error compat rewrite result:
230  * compat_kr: the more-compatible return value
231  * should_rewrite: true if compat_kr should be returned
232  * should_telemeter: true if compat_kr should be telemetered
233  */
234 typedef struct {
235 	kern_return_t compat_kr;
236 	bool should_rewrite;
237 	bool should_telemeter;
238 } vm_sanitize_compat_rewrite_t;
239 
240 typedef vm_sanitize_compat_rewrite_t (*vm_sanitize_err_compat_addr_size_fn)(kern_return_t kr,
241     vm_address_t addr, vm_size_t size, vm_offset_t pgmask, vm_map_t map_or_null);
242 typedef vm_sanitize_compat_rewrite_t (*vm_sanitize_err_compat_cur_and_max_prots_fn)(kern_return_t kr,
243     vm_prot_t *cur_inout, vm_prot_t *max_inout, vm_prot_t extra_mask);
244 
245 typedef const struct vm_sanitize_caller {
246 	vm_sanitize_caller_id_t              vmsc_caller_id;
247 	const char                          *vmsc_caller_name;
248 	vm_sanitize_method_t                 vmsc_telemetry_id;
249 	enum vm_sanitize_subsys_error_codes  vmsc_ktriage_id;
250 
251 	vm_sanitize_err_compat_addr_size_fn    err_compat_addr_size;
252 	vm_sanitize_err_compat_cur_and_max_prots_fn err_compat_prot_cur_max;
253 } *vm_sanitize_caller_t;
254 
255 /*
256  * Macros to declare and define callers of sanitization functions
257  */
258 #define VM_SANITIZE_DECL_CALLER(name) \
259 	extern vm_sanitize_caller_t const VM_SANITIZE_CALLER_ ## name;
260 
261 #define VM_SANITIZE_DEFINE_CALLER(name, ... /* error compat functions */)       \
262 	static const struct vm_sanitize_caller vm_sanitize_caller_storage_ ## name = { \
263 	    .vmsc_caller_id = VM_SANITIZE_CALLER_ID_ ## name,        \
264 	    .vmsc_caller_name = #name,                       \
265 	    .vmsc_telemetry_id = VM_SANITIZE_METHOD_ ## name,     \
266 	    .vmsc_ktriage_id = KDBG_TRIAGE_VM_SANITIZE_ ## name,  \
267 	    __VA_ARGS__                                     \
268 	}; \
269 	vm_sanitize_caller_t const VM_SANITIZE_CALLER_ ## name = &vm_sanitize_caller_storage_ ## name
270 
271 /*
272  * Declaration of callers of VM sanitization functions
273  */
274 /* memory entry */
275 VM_SANITIZE_DECL_CALLER(MACH_MAKE_MEMORY_ENTRY);
276 VM_SANITIZE_DECL_CALLER(MACH_MEMORY_ENTRY_PAGE_OP);
277 VM_SANITIZE_DECL_CALLER(MACH_MEMORY_ENTRY_RANGE_OP);
278 VM_SANITIZE_DECL_CALLER(MACH_MEMORY_ENTRY_MAP_SIZE);
279 VM_SANITIZE_DECL_CALLER(MACH_MEMORY_OBJECT_MEMORY_ENTRY);
280 
281 /* alloc/dealloc */
282 VM_SANITIZE_DECL_CALLER(VM_ALLOCATE_FIXED);
283 VM_SANITIZE_DECL_CALLER(VM_ALLOCATE_ANYWHERE);
284 VM_SANITIZE_DECL_CALLER(VM_DEALLOCATE);
285 VM_SANITIZE_DECL_CALLER(MUNMAP);
286 
287 /* map/remap */
288 VM_SANITIZE_DECL_CALLER(VM_MAP_REMAP);
289 VM_SANITIZE_DECL_CALLER(MMAP);
290 VM_SANITIZE_DECL_CALLER(MREMAP_ENCRYPTED);
291 VM_SANITIZE_DECL_CALLER(MAP_WITH_LINKING_NP);
292 VM_SANITIZE_DECL_CALLER(ENTER_MEM_OBJ);
293 VM_SANITIZE_DECL_CALLER(ENTER_MEM_OBJ_CTL);
294 
295 /* wire/unwire */
296 VM_SANITIZE_DECL_CALLER(VM_WIRE_USER);
297 VM_SANITIZE_DECL_CALLER(VM_UNWIRE_USER);
298 VM_SANITIZE_DECL_CALLER(VM_MAP_WIRE);
299 VM_SANITIZE_DECL_CALLER(VM_MAP_UNWIRE);
300 VM_SANITIZE_DECL_CALLER(VSLOCK);
301 VM_SANITIZE_DECL_CALLER(VSUNLOCK);
302 
303 /* copyin/copyout */
304 VM_SANITIZE_DECL_CALLER(VM_MAP_COPY_OVERWRITE);
305 VM_SANITIZE_DECL_CALLER(VM_MAP_COPYIN);
306 VM_SANITIZE_DECL_CALLER(VM_MAP_READ_USER);
307 VM_SANITIZE_DECL_CALLER(VM_MAP_WRITE_USER);
308 
309 /* inherit */
310 VM_SANITIZE_DECL_CALLER(MACH_VM_INHERIT);
311 VM_SANITIZE_DECL_CALLER(VM_INHERIT);
312 VM_SANITIZE_DECL_CALLER(VM32_INHERIT);
313 VM_SANITIZE_DECL_CALLER(VM_MAP_INHERIT);
314 VM_SANITIZE_DECL_CALLER(MINHERIT);
315 
316 /* protect */
317 VM_SANITIZE_DECL_CALLER(MACH_VM_PROTECT);
318 VM_SANITIZE_DECL_CALLER(VM_PROTECT);
319 VM_SANITIZE_DECL_CALLER(VM32_PROTECT);
320 VM_SANITIZE_DECL_CALLER(VM_MAP_PROTECT);
321 VM_SANITIZE_DECL_CALLER(MPROTECT);
322 VM_SANITIZE_DECL_CALLER(USERACC);
323 
324 /* behavior */
325 VM_SANITIZE_DECL_CALLER(VM_BEHAVIOR_SET);
326 VM_SANITIZE_DECL_CALLER(MADVISE);
327 
328 /* msync */
329 VM_SANITIZE_DECL_CALLER(VM_MAP_MSYNC);
330 VM_SANITIZE_DECL_CALLER(MSYNC);
331 
332 /* machine attribute */
333 VM_SANITIZE_DECL_CALLER(VM_MAP_MACHINE_ATTRIBUTE);
334 
335 /* page info */
336 VM_SANITIZE_DECL_CALLER(VM_MAP_PAGE_RANGE_INFO);
337 VM_SANITIZE_DECL_CALLER(VM_MAP_PAGE_RANGE_QUERY);
338 VM_SANITIZE_DECL_CALLER(MINCORE);
339 
340 /* single */
341 VM_SANITIZE_DECL_CALLER(MACH_VM_DEFERRED_RECLAMATION_BUFFER_INIT);
342 VM_SANITIZE_DECL_CALLER(MACH_VM_RANGE_CREATE);
343 VM_SANITIZE_DECL_CALLER(SHARED_REGION_MAP_AND_SLIDE_2_NP);
344 
345 /* test */
346 VM_SANITIZE_DECL_CALLER(TEST);
347 
348 /*
349  * Macro that extracts the inner struct member from a wrapped type. Should be
350  * used in all cases, including validation functions, when accessing the
351  * inner struct member.
352  */
353 #define VM_SANITIZE_UNSAFE_UNWRAP(_val) (_val).UNSAFE
354 
355 /*
356  * Macro to check if unsafe value is a specific safe value
357  */
358 #define VM_SANITIZE_UNSAFE_IS_EQUAL(_var, _val) ((_var).UNSAFE == (_val))
359 
360 /*
361  * Macro to check if unsafe value is zero
362  */
363 #define VM_SANITIZE_UNSAFE_IS_ZERO(_var) VM_SANITIZE_UNSAFE_IS_EQUAL(_var, 0)
364 
365 /*
366  * returns whether a given unsafe value fits a given type
367  */
368 #define VM_SANITIZE_UNSAFE_FITS(_var, type_t) ({ \
369 	__auto_type __tmp = (_var).UNSAFE; \
370 	__tmp == (type_t)__tmp;            \
371 })
372 
373 /*
374  * Macro that sets a value of unsafe type to a value of safe type.
375  * This is safe to do because we are only forcing ourselves to perform
376  * checks on a value we already have direct access to.
377  */
378 #define VM_SANITIZE_UT_SET(_var, _val) ((_var).UNSAFE) = (_val)
379 
380 /*!
381  * @function vm_sanitize_wrap_addr
382  *
383  * @abstract
384  * Function that wraps unsanitized safe address into unsafe address
385  *
386  * @param val               safe address
387  * @returns                 unsafe address
388  */
389 __attribute__((always_inline, warn_unused_result))
390 vm_addr_struct_t vm_sanitize_wrap_addr(vm_address_t val);
391 
392 /*!
393  * @function vm_sanitize_wrap_addr_ref
394  *
395  * @abstract
396  * Function that wraps a safe address pointer,
397  * into unsafe address pointer.
398  *
399  * @param val               safe address ref
400  * @returns                 unsafe address reference
401  */
402 #define vm_sanitize_wrap_addr_ref(var)  _Generic(var, \
403 	mach_vm_address_t *: (vm_addr_struct_t *)(var), \
404 	vm_address_t *:      (vm_addr_struct_t *)(var), \
405 	default:             (var))
406 
407 /*!
408  * @function vm_sanitize_wrap_size
409  *
410  * @abstract
411  * Function that wraps unsanitized safe size into unsafe size
412  *
413  * @param val               safe size
414  * @returns                 unsafe size
415  */
416 __attribute__((always_inline, warn_unused_result))
417 vm_size_struct_t vm_sanitize_wrap_size(vm_size_t val);
418 
419 /*
420  * bsd doesn't use 32bit interfaces and the types aren't even defined for them,
421  * so we just expose this to MACH.
422  */
423 #ifdef MACH_KERNEL_PRIVATE
424 /*!
425  * @function vm32_sanitize_wrap_size
426  *
427  * @abstract
428  * Function that wraps unsanitized 32bit safe size into 32bit unsafe size
429  *
430  * @param val               safe size
431  * @returns                 unsafe size
432  */
433 __attribute__((always_inline, warn_unused_result))
434 vm32_size_struct_t vm32_sanitize_wrap_size(vm32_size_t val);
435 #endif /* MACH_KERNEL_PRIVATE */
436 
437 /*!
438  * @function vm_sanitize_wrap_prot
439  *
440  * @abstract
441  * Function that wraps unsanitized safe protection into unsafe protection
442  *
443  * @param val               safe protection
444  * @returns                 unsafe protection
445  */
446 __attribute__((always_inline, warn_unused_result))
447 vm_prot_ut vm_sanitize_wrap_prot(vm_prot_t val);
448 
449 /*!
450  * @function vm_sanitize_wrap_prot_ref
451  *
452  * @abstract
453  * Function that wraps a safe protection pointer into unsafe protection pointer.
454  *
455  * @param val               safe protection pointer
456  * @returns                 unsafe protection pointer
457  */
458 __attribute__((always_inline, warn_unused_result))
459 static inline vm_prot_ut *
vm_sanitize_wrap_prot_ref(vm_prot_t * val)460 vm_sanitize_wrap_prot_ref(vm_prot_t *val)
461 {
462 	return (vm_prot_ut *)val;
463 }
464 
465 /*!
466  * @function vm_sanitize_wrap_inherit
467  *
468  * @abstract
469  * Function that wraps unsanitized safe vm_inherit into unsafe vm_inherit
470  *
471  * @param val               safe vm_inherit
472  * @returns                 unsafe vm_inherit
473  */
474 __attribute__((always_inline, warn_unused_result))
475 vm_inherit_ut vm_sanitize_wrap_inherit(vm_inherit_t val);
476 
477 /*!
478  * @function vm_sanitize_wrap_behavior
479  *
480  * @abstract
481  * Function that wraps a safe vm_behavior into an unsafe vm_behavior
482  *
483  * @param val               safe vm_behavior
484  * @returns                 unsafe vm_behavior
485  */
486 __attribute__((always_inline, warn_unused_result))
487 vm_behavior_ut vm_sanitize_wrap_behavior(vm_behavior_t val);
488 
489 #ifdef  MACH_KERNEL_PRIVATE
490 
491 /*!
492  * @function vm_sanitize_expand_addr_to_64
493  *
494  * @abstract
495  * Function used by the vm32 functions to cast 32bit unsafe address
496  * to 64bit unsafe address
497  *
498  * @param val               32bit unsafe address
499  * @returns                 64bit unsafe address
500  */
501 __attribute__((always_inline, warn_unused_result))
502 vm_addr_struct_t vm_sanitize_expand_addr_to_64(vm32_address_ut val);
503 
504 /*!
505  * @function vm_sanitize_expand_size_to_64
506  *
507  * @abstract
508  * Function used by the vm32 functions to cast 32bit unsafe size
509  * to 64bit unsafe size
510  *
511  * @param val               32bit unsafe size
512  * @returns                 64bit unsafe size
513  */
514 __attribute__((always_inline, warn_unused_result))
515 vm_size_struct_t vm_sanitize_expand_size_to_64(vm32_size_ut val);
516 
517 /*!
518  * @function vm_sanitize_trunc_addr_to_32
519  *
520  * @abstract
521  * Function used by the vm32 functions to cast 64bit unsafe address
522  * to 32bit unsafe address
523  *
524  * @param val               64bit unsafe address
525  * @returns                 32bit unsafe address
526  */
527 __attribute__((always_inline, warn_unused_result))
528 vm32_address_ut vm_sanitize_trunc_addr_to_32(vm_addr_struct_t val);
529 
530 /*!
531  * @function vm_sanitize_trunc_size_to_32
532  *
533  * @abstract
534  * Function used by the vm32 functions to cast 64bit unsafe size
535  * to 32bit unsafe size
536  *
537  * @param val               64bit unsafe size
538  * @returns                 32bit unsafe size
539  */
540 __attribute__((always_inline, warn_unused_result))
541 vm32_size_ut vm_sanitize_trunc_size_to_32(vm_size_struct_t val);
542 
543 /*!
544  * @function vm_sanitize_add_overflow()
545  *
546  * @abstract
547  * Computes the sum of an address and a size checking for overflow,
548  * staying in the unsafe world.
549  *
550  * @param addr_u            unsafe address
551  * @param size_u            unsafe size
552  * @param addr_out_u        unsafe result
553  * @returns whether the operation overflowed
554  */
555 __attribute__((always_inline, warn_unused_result, overloadable))
556 bool vm_sanitize_add_overflow(
557 	vm32_address_ut         addr_u,
558 	vm32_size_ut            size_u,
559 	vm32_address_ut        *addr_out_u);
560 
561 #endif  /* MACH_KERNEL_PRIVATE */
562 
563 /*!
564  * @function vm_sanitize_add_overflow()
565  *
566  * @abstract
567  * Computes the sum of an address and a size checking for overflow,
568  * staying in the unsafe world.
569  *
570  * @param addr_u            unsafe address
571  * @param size_u            unsafe size
572  * @param addr_out_u        unsafe result
573  * @returns whether the operation overflowed
574  */
575 __attribute__((always_inline, warn_unused_result, overloadable))
576 bool vm_sanitize_add_overflow(
577 	vm_addr_struct_t        addr_u,
578 	vm_size_struct_t        size_u,
579 	vm_addr_struct_t       *addr_out_u);
580 
581 /*!
582  * @function vm_sanitize_add_overflow()
583  *
584  * @abstract
585  * Computes the sum of two sizes checking for overflow,
586  * staying in the unsafe world.
587  *
588  * @param size1_u           unsafe size 1
589  * @param size2_u           unsafe size 2
590  * @param size_out_u        unsafe result
591  * @returns whether the operation overflowed
592  */
593 __attribute__((always_inline, warn_unused_result, overloadable))
594 bool vm_sanitize_add_overflow(
595 	vm_size_struct_t        size1_u,
596 	vm_size_struct_t        size2_u,
597 	vm_size_struct_t       *size_out_u);
598 
599 /*!
600  * @function vm_sanitize_compute_ut_end
601  *
602  * @abstract
603  * Computes and returns unsafe end from unsafe start and size
604  *
605  * @param addr_u            unsafe start
606  * @param size_u            unsafe size
607  * @returns                 unsafe end
608  */
609 __attribute__((always_inline, warn_unused_result))
610 vm_addr_struct_t vm_sanitize_compute_ut_end(
611 	vm_addr_struct_t        addr_u,
612 	vm_size_struct_t        size_u);
613 
614 /*!
615  * @function vm_sanitize_compute_ut_size
616  *
617  * @abstract
618  * Computes and returns unsafe size from unsafe start and end
619  *
620  * @param addr_u            unsafe start
621  * @param end_u             unsafe end
622  * @returns                 unsafe size
623  */
624 __attribute__((always_inline, warn_unused_result))
625 vm_size_struct_t vm_sanitize_compute_ut_size(
626 	vm_addr_struct_t        addr_u,
627 	vm_addr_struct_t        end_u);
628 
629 /*!
630  * @function vm_sanitize_addr
631  *
632  * @abstract
633  * Sanitization function that takes unsafe address, and returns a truncated
634  * address.
635  *
636  * @param map               map the address belongs to
637  * @param addr_u            unsafe address to sanitize
638  * @returns                 a sanitized address
639  */
640 __attribute__((always_inline, warn_unused_result))
641 mach_vm_address_t vm_sanitize_addr(
642 	vm_map_t                map,
643 	vm_addr_struct_t        addr_u);
644 
645 /*!
646  * @function vm_sanitize_offset_in_page
647  *
648  * @abstract
649  * Sanitization function that takes unsafe address,
650  * and returns the offset in the page for this address.
651  *
652  * @param mask              page mask to use
653  * @param addr_u            unsafe address to sanitize
654  * @returns                 a sanitized offset in page
655  */
656 __attribute__((always_inline, warn_unused_result))
657 mach_vm_offset_t vm_sanitize_offset_in_page(
658 	vm_map_offset_t         mask,
659 	vm_addr_struct_t        addr_u);
660 
661 /*
662  * @function vm_sanitize_offset_in_page
663  *
664  * @abstract
665  * Sanitization function that takes unsafe address,
666  * and returns the offset in the page for this address.
667  *
668  * @param map               map the address belongs to
669  * @param addr_u            unsafe address to sanitize
670  * @returns                 a sanitized offset in page
671  */
672 __attribute__((always_inline, warn_unused_result, overloadable))
673 static inline mach_vm_offset_t
vm_sanitize_offset_in_page(vm_map_t map,vm_addr_struct_t addr_u)674 vm_sanitize_offset_in_page(
675 	vm_map_t                map,
676 	vm_addr_struct_t        addr_u)
677 {
678 	return vm_sanitize_offset_in_page(vm_map_page_mask(map), addr_u);
679 }
680 
681 /*!
682  * @function vm_sanitize_offset
683  *
684  * @abstract
685  * Sanitization function that takes unsafe offset and validates
686  * that it is within addr and end provided.
687  *
688  * @param offset_u          unsafe offset to sanitize
689  * @param vm_sanitize_caller        caller of the sanitization function
690  * @param addr              sanitized start address
691  * @param end               sanitized end address
692  * @param offset            sanitized offset
693  * @returns                 return code indicating success/failure of sanitization
694  */
695 __attribute__((always_inline, warn_unused_result))
696 kern_return_t vm_sanitize_offset(
697 	vm_addr_struct_t        offset_u,
698 	vm_sanitize_caller_t    vm_sanitize_caller,
699 	vm_map_address_t        addr,
700 	vm_map_address_t        end,
701 	vm_map_offset_t        *offset);
702 
703 /*!
704  * @function vm_sanitize_mask
705  *
706  * @abstract
707  * Sanitization function that takes unsafe mask and sanitizes it.
708  *
709  * @param mask_u            unsafe mask to sanitize
710  * @param vm_sanitize_caller        caller of the sanitization function
711  * @param mask              sanitized mask
712  * @returns                 return code indicating success/failure of sanitization
713  */
714 __attribute__((always_inline, warn_unused_result))
715 kern_return_t vm_sanitize_mask(
716 	vm_addr_struct_t        mask_u,
717 	vm_sanitize_caller_t    vm_sanitize_caller,
718 	vm_map_offset_t        *mask);
719 
720 /*!
721  * @function vm_sanitize_object_size
722  *
723  * @abstract
724  * Sanitization function that takes unsafe VM object size and safely rounds it
725  * up wrt a VM object.
726  *
727  * @param size_u            unsafe size to sanitize
728  * @param vm_sanitize_caller        caller of the sanitization function
729  * @param flags             flags that influence sanitization performed
730  * @param size              sanitized object size
731  * @returns                 return code indicating success/failure of sanitization
732  */
733 __attribute__((always_inline, warn_unused_result))
734 kern_return_t vm_sanitize_object_size(
735 	vm_size_struct_t        size_u,
736 	vm_sanitize_caller_t    vm_sanitize_caller,
737 	vm_sanitize_flags_t     flags,
738 	vm_object_offset_t     *size)
739 __vm_sanitize_require_size_zero_flag(flags);
740 
741 /*!
742  * @function vm_sanitize_size
743  *
744  * @abstract
745  * Sanitization function that takes unsafe size and safely rounds it up.
746  *
747  * @param offset_u          an offset/address which marks the beginning of the
748  *                          memory region of size @c size_u. Overflow checks
749  *                          will be performed on @c size_u+offset_u, and the
750  *                          low bits of @c offset_u may influence the rounding
751  *                          of @c size_u to ensure the returned size covers all
752  *                          pages that intersect with the region that starts at
753  *                          @c offset_u and has size @c size_u.
754  * @param size_u            unsafe size to sanitize
755  * @param vm_sanitize_caller        caller of the sanitization function
756  * @param map               map the address belongs to
757  * @param flags             flags that influence sanitization performed
758  * @param size              sanitized size
759  * @returns                 return code indicating success/failure of sanitization
760  */
761 __attribute__((always_inline, warn_unused_result))
762 kern_return_t vm_sanitize_size(
763 	vm_addr_struct_t        offset_u,
764 	vm_size_struct_t        size_u,
765 	vm_sanitize_caller_t    vm_sanitize_caller,
766 	vm_map_t                map,
767 	vm_sanitize_flags_t     flags,
768 	mach_vm_size_t         *size)
769 __vm_sanitize_require_size_zero_flag(flags);
770 
771 /*!
772  * @function vm_sanitize_addr_size
773  *
774  * @abstract
775  * Sanitization function that takes unsafe address and size and returns
776  * sanitized start, end and size via out parameters.
777  *
778  * @param addr_u            unsafe address to sanitize
779  * @param size_u            unsafe size to sanitize
780  * @param vm_sanitize_caller        caller of the sanitization function
781  * @param mask              page mask to use
782  * @param map_or_null       optional map, used for error compat for some callers
783  * @param flags             flags that influence sanitization performed
784  * @param addr              sanitized start
785  * @param end               sanitized end
786  * @param size              sanitized size
787  * @returns                 return code indicating success/failure of sanitization
788  */
789 __attribute__((always_inline, warn_unused_result))
790 kern_return_t vm_sanitize_addr_size(
791 	vm_addr_struct_t        addr_u,
792 	vm_size_struct_t        size_u,
793 	vm_sanitize_caller_t    vm_sanitize_caller,
794 	mach_vm_offset_t        mask,
795 	vm_map_t                map_or_null,
796 	vm_sanitize_flags_t     flags,
797 	vm_map_offset_t        *addr,
798 	vm_map_offset_t        *end,
799 	vm_map_size_t          *size)
800 __vm_sanitize_require_size_zero_flag(flags);
801 
802 /*!
803  * @function vm_sanitize_addr_size
804  *
805  * @abstract
806  * Sanitization function that takes unsafe address and size and returns
807  * sanitized start, end and size via out parameters.
808  *
809  * @param addr_u            unsafe address to sanitize
810  * @param size_u            unsafe size to sanitize
811  * @param vm_sanitize_caller        caller of the sanitization function
812  * @param mask              page mask to use
813  * @param flags             flags that influence sanitization performed
814  * @param addr              sanitized start
815  * @param end               sanitized end
816  * @param size              sanitized size
817  * @returns                 return code indicating success/failure of sanitization
818  */
819 __attribute__((always_inline, warn_unused_result, overloadable))
820 static inline kern_return_t
vm_sanitize_addr_size(vm_addr_struct_t addr_u,vm_size_struct_t size_u,vm_sanitize_caller_t vm_sanitize_caller,mach_vm_offset_t mask,vm_sanitize_flags_t flags,vm_map_offset_t * addr,vm_map_offset_t * end,vm_map_size_t * size)821 vm_sanitize_addr_size(
822 	vm_addr_struct_t        addr_u,
823 	vm_size_struct_t        size_u,
824 	vm_sanitize_caller_t    vm_sanitize_caller,
825 	mach_vm_offset_t        mask,
826 	vm_sanitize_flags_t     flags,
827 	vm_map_offset_t        *addr,
828 	vm_map_offset_t        *end,
829 	vm_map_size_t          *size)
830 __vm_sanitize_require_size_zero_flag(flags)
831 {
832 	return vm_sanitize_addr_size(addr_u, size_u, vm_sanitize_caller, mask,
833 	           VM_MAP_NULL, flags, addr, end, size);
834 }
835 
836 
837 /*!
838  * @function vm_sanitize_addr_size
839  *
840  * @abstract
841  * Sanitization function that takes unsafe address and size and returns
842  * sanitized start, end and size via out parameters.
843  *
844  * @param addr_u            unsafe address to sanitize
845  * @param size_u            unsafe size to sanitize
846  * @param vm_sanitize_caller        caller of the sanitization function
847  * @param map               map the address belongs to
848  * @param flags             flags that influence sanitization performed
849  * @param addr              sanitized start
850  * @param end               sanitized end
851  * @param size              sanitized size
852  * @returns                 return code indicating success/failure of sanitization
853  */
854 __attribute__((always_inline, warn_unused_result, overloadable))
855 static inline kern_return_t
vm_sanitize_addr_size(vm_addr_struct_t addr_u,vm_size_struct_t size_u,vm_sanitize_caller_t vm_sanitize_caller,vm_map_t map,vm_sanitize_flags_t flags,vm_map_offset_t * addr,vm_map_offset_t * end,vm_map_size_t * size)856 vm_sanitize_addr_size(
857 	vm_addr_struct_t        addr_u,
858 	vm_size_struct_t        size_u,
859 	vm_sanitize_caller_t    vm_sanitize_caller,
860 	vm_map_t                map,
861 	vm_sanitize_flags_t     flags,
862 	vm_map_offset_t        *addr,
863 	vm_map_offset_t        *end,
864 	vm_map_size_t          *size)
865 __vm_sanitize_require_size_zero_flag(flags)
866 {
867 	mach_vm_offset_t mask = vm_map_page_mask(map);
868 
869 	return vm_sanitize_addr_size(addr_u, size_u, vm_sanitize_caller, mask,
870 	           map, flags, addr, end, size);
871 }
872 
873 /*!
874  * @function vm_sanitize_addr_end
875  *
876  * @abstract
877  * Sanitization function that takes unsafe address and end and returns
878  * sanitized start, end and size via out parameters.
879  *
880  * @param addr_u            unsafe address to sanitize
881  * @param end_u             unsafe end to sanitize
882  * @param vm_sanitize_caller        caller of the sanitization function
883  * @param mask              page mask to use
884  * @param map_or_null       optional map, used for error compat for some callers
885  * @param flags             flags that influence sanitization performed
886  * @param start             sanitized start
887  * @param end               sanitized end
888  * @param size              sanitized size
889  * @returns                 return code indicating success/failure of sanitization
890  */
891 __attribute__((always_inline, warn_unused_result))
892 kern_return_t vm_sanitize_addr_end(
893 	vm_addr_struct_t        addr_u,
894 	vm_addr_struct_t        end_u,
895 	vm_sanitize_caller_t    vm_sanitize_caller,
896 	mach_vm_offset_t        mask,
897 	vm_map_t                map_or_null,
898 	vm_sanitize_flags_t     flags,
899 	vm_map_offset_t        *start,
900 	vm_map_offset_t        *end,
901 	vm_map_size_t          *size)
902 __vm_sanitize_require_size_zero_flag(flags);
903 
904 /*!
905  * @function vm_sanitize_addr_end
906  *
907  * @abstract
908  * Sanitization function that takes unsafe address and end and returns
909  * sanitized start, end and size via out parameters.
910  *
911  * @param addr_u            unsafe address to sanitize
912  * @param end_u             unsafe end to sanitize
913  * @param vm_sanitize_caller        caller of the sanitization function
914  * @param mask              page mask to use
915  * @param flags             flags that influence sanitization performed
916  * @param start             sanitized start
917  * @param end               sanitized end
918  * @param size              sanitized size
919  * @returns                 return code indicating success/failure of sanitization
920  */
921 __attribute__((always_inline, warn_unused_result, overloadable))
922 static inline kern_return_t
vm_sanitize_addr_end(vm_addr_struct_t addr_u,vm_addr_struct_t end_u,vm_sanitize_caller_t vm_sanitize_caller,mach_vm_offset_t mask,vm_sanitize_flags_t flags,vm_map_offset_t * start,vm_map_offset_t * end,vm_map_size_t * size)923 vm_sanitize_addr_end(
924 	vm_addr_struct_t        addr_u,
925 	vm_addr_struct_t        end_u,
926 	vm_sanitize_caller_t    vm_sanitize_caller,
927 	mach_vm_offset_t        mask,
928 	vm_sanitize_flags_t     flags,
929 	vm_map_offset_t        *start,
930 	vm_map_offset_t        *end,
931 	vm_map_size_t          *size)
932 __vm_sanitize_require_size_zero_flag(flags)
933 {
934 	return vm_sanitize_addr_end(addr_u, end_u, vm_sanitize_caller, mask,
935 	           VM_MAP_NULL, flags, start, end, size);
936 }
937 
938 /*!
939  * @function vm_sanitize_addr_end
940  *
941  * @abstract
942  * Sanitization function that takes unsafe address and end and returns
943  * sanitized start, end and size via out parameters.
944  *
945  * @param addr_u            unsafe address to sanitize
946  * @param end_u             unsafe end to sanitize
947  * @param vm_sanitize_caller        caller of the sanitization function
948  * @param map               map the address belongs to
949  * @param flags             flags that influence sanitization performed
950  * @param start             sanitized start
951  * @param end               sanitized end
952  * @param size              sanitized size
953  * @returns                 return code indicating success/failure of sanitization
954  */
955 __attribute__((always_inline, warn_unused_result, overloadable))
956 static inline kern_return_t
vm_sanitize_addr_end(vm_addr_struct_t addr_u,vm_addr_struct_t end_u,vm_sanitize_caller_t vm_sanitize_caller,vm_map_t map,vm_sanitize_flags_t flags,vm_map_offset_t * start,vm_map_offset_t * end,vm_map_size_t * size)957 vm_sanitize_addr_end(
958 	vm_addr_struct_t        addr_u,
959 	vm_addr_struct_t        end_u,
960 	vm_sanitize_caller_t    vm_sanitize_caller,
961 	vm_map_t                map,
962 	vm_sanitize_flags_t     flags,
963 	vm_map_offset_t        *start,
964 	vm_map_offset_t        *end,
965 	vm_map_size_t          *size)
966 __vm_sanitize_require_size_zero_flag(flags)
967 {
968 	mach_vm_offset_t mask = vm_map_page_mask(map);
969 
970 	return vm_sanitize_addr_end(addr_u, end_u, vm_sanitize_caller, mask,
971 	           map, flags, start, end, size);
972 }
973 
974 /*!
975  * @function vm_sanitize_prot
976  *
977  * @abstract
978  * Sanitization function that takes unsafe protections and sanitizes it.
979  *
980  * @param prot_u            unsafe protections
981  * @param vm_sanitize_caller        caller of the sanitization function
982  * @param map               map in which protections are going to be changed
983  * @param extra_mask        extra mask to allow on top of (VM_PROT_ALL | VM_PROT_ALLEXEC)
984  * @param prot              sanitized protections
985  * @returns                 return code indicating success/failure of sanitization
986  */
987 __attribute__((always_inline, warn_unused_result))
988 kern_return_t vm_sanitize_prot(
989 	vm_prot_ut              prot_u,
990 	vm_sanitize_caller_t    vm_sanitize_caller,
991 	vm_map_t                map,
992 	vm_prot_t               extra_mask,
993 	vm_prot_t              *prot);
994 
995 __attribute__((always_inline, warn_unused_result, overloadable))
996 static inline kern_return_t
vm_sanitize_prot(vm_prot_ut prot_u,vm_sanitize_caller_t vm_sanitize_caller,vm_map_t map,vm_prot_t * prot)997 vm_sanitize_prot(
998 	vm_prot_ut              prot_u,
999 	vm_sanitize_caller_t    vm_sanitize_caller,
1000 	vm_map_t                map,
1001 	vm_prot_t              *prot)
1002 {
1003 	return vm_sanitize_prot(prot_u, vm_sanitize_caller, map, VM_PROT_NONE, prot);
1004 }
1005 
1006 /*!
1007  * @function vm_sanitize_cur_and_max_prots
1008  *
1009  * @abstract
1010  * Sanitization function that takes a pair of unsafe current and max protections
1011  * and sanitizes it.
1012  *
1013  * @param cur_prot_u        unsafe current protections
1014  * @param max_prot_u        unsafe max protections
1015  * @param vm_sanitize_caller        caller of the sanitization function
1016  * @param map               map in which protections are going to be changed
1017  * @param extra_mask        extra mask to allow on top of (VM_PROT_ALL | VM_PROT_ALLEXEC)
1018  * @param cur_prot          sanitized current protections
1019  * @param max_prot          sanitized max protections
1020  * @returns                 return code indicating success/failure of sanitization
1021  */
1022 __attribute__((always_inline, warn_unused_result))
1023 kern_return_t vm_sanitize_cur_and_max_prots(
1024 	vm_prot_ut              cur_prot_u,
1025 	vm_prot_ut              max_prot_u,
1026 	vm_sanitize_caller_t    vm_sanitize_caller,
1027 	vm_map_t                map,
1028 	vm_prot_t               extra_mask,
1029 	vm_prot_t              *cur_prot,
1030 	vm_prot_t              *max_prot);
1031 
1032 __attribute__((always_inline, warn_unused_result, overloadable))
1033 static inline kern_return_t
vm_sanitize_cur_and_max_prots(vm_prot_ut cur_prot_u,vm_prot_ut max_prot_u,vm_sanitize_caller_t vm_sanitize_caller,vm_map_t map,vm_prot_t * cur_prot,vm_prot_t * max_prot)1034 vm_sanitize_cur_and_max_prots(
1035 	vm_prot_ut              cur_prot_u,
1036 	vm_prot_ut              max_prot_u,
1037 	vm_sanitize_caller_t    vm_sanitize_caller,
1038 	vm_map_t                map,
1039 	vm_prot_t              *cur_prot,
1040 	vm_prot_t              *max_prot)
1041 {
1042 	return vm_sanitize_cur_and_max_prots(cur_prot_u, max_prot_u, vm_sanitize_caller, map,
1043 	           VM_PROT_NONE, cur_prot, max_prot);
1044 }
1045 
1046 /*!
1047  * @function vm_sanitize_memory_entry_perm
1048  *
1049  * @abstract
1050  * Sanitization function that takes unsafe memory entry permissions and
1051  * sanitizes it.
1052  *
1053  * @param perm_u            unsafe permissions to sanitize
1054  * @param vm_sanitize_caller        caller of the sanitization function
1055  * @param flags             flags that influence sanitization performed
1056  * @param extra_mask        extra mask to allow on top of VM_PROT_ALL
1057  * @param perm              sanitized memory entry permissions
1058  * @returns                 return code indicating success/failure of sanitization
1059  */
1060 __attribute__((always_inline, warn_unused_result))
1061 kern_return_t vm_sanitize_memory_entry_perm(
1062 	vm_prot_ut              perm_u,
1063 	vm_sanitize_caller_t    vm_sanitize_caller,
1064 	vm_sanitize_flags_t     flags,
1065 	vm_prot_t               extra_mask,
1066 	vm_prot_t              *perm);
1067 
1068 /*!
1069  * @function vm_sanitize_prot_bsd
1070  *
1071  * @abstract
1072  * Sanitization function that takes unsafe protections and sanitizes it.
1073  *
1074  * @discussion
1075  * Use this function for BSD callers as it strips invalid protections instead
1076  * of returning an error.
1077  *
1078  * @param prot_u            unsafe protections
1079  * @param vm_sanitize_caller        caller of the sanitization function
1080  * @returns                 sanitized protections
1081  */
1082 __attribute__((always_inline, warn_unused_result))
1083 vm_prot_t vm_sanitize_prot_bsd(
1084 	vm_prot_ut              prot_u,
1085 	vm_sanitize_caller_t    vm_sanitize_caller);
1086 
1087 /*!
1088  * @function vm_sanitize_inherit
1089  *
1090  * @abstract
1091  * Sanitization function that takes unsafe vm_inherit and sanitizes it.
1092  *
1093  * @param inherit_u         unsafe vm_inherit
1094  * @param vm_sanitize_caller        caller of the sanitization function
1095  * @param inherit           sanitized vm_inherit
1096  * @returns                 return code indicating success/failure of sanitization
1097  */
1098 __attribute__((always_inline, warn_unused_result))
1099 kern_return_t vm_sanitize_inherit(
1100 	vm_inherit_ut           inherit_u,
1101 	vm_sanitize_caller_t    vm_sanitize_caller,
1102 	vm_inherit_t           *inherit);
1103 
1104 /*!
1105  * @function vm_sanitize_behavior
1106  *
1107  * @abstract
1108  * Sanitization function that takes an unsafe vm_behavior and sanitizes it.
1109  *
1110  * @param behavior_u         unsafe vm_behavior
1111  * @param vm_sanitize_caller caller of the sanitization function
1112  * @param behavior           sanitized vm_behavior
1113  * @returns                  return code indicating success/failure of sanitization
1114  */
1115 __attribute__((always_inline, warn_unused_result))
1116 kern_return_t vm_sanitize_behavior(
1117 	vm_behavior_ut           behavior_u,
1118 	vm_sanitize_caller_t    vm_sanitize_caller __unused,
1119 	vm_behavior_t           *behavior);
1120 
1121 #pragma GCC visibility pop
1122 __END_DECLS
1123 #endif /* _VM_SANITIZE_INTERNAL_H_ */
1124