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