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