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_UNSAFE_TYPES_H_ 30 #define _VM_UNSAFE_TYPES_H_ 31 32 #include <mach/vm_types.h> 33 34 /* 35 * Macro to generate a wrapped "struct" that preserves ABI, 36 * but prevents direct manipulation of the type. 37 * 38 * The transparent union is needed because of arm64 which for "Composite" 39 * arguments passed on the stack will align them to 8 byte boundaries as per 40 * spec: 41 * 42 * If the argument is an alignment adjusted type its value is passed as 43 * a copy of the actual value. The copy will have an alignment defined as 44 * follows: 45 * 46 * - For a Fundamental Data Type, the alignment is the natural alignment 47 * of that type, after any promotions. 48 * - For a Composite Type, the alignment of the copy will have 8-byte 49 * alignment if its natural alignment is ≤ 8 and 16-byte alignment 50 * if its natural alignment is ≥ 16. 51 */ 52 #if defined(__cplusplus) 53 #define VM_GENERATE_UNSAFE_WRAPPER(_safe_type, _unsafe_type) \ 54 typedef _safe_type _unsafe_type 55 #else 56 #define VM_GENERATE_UNSAFE_WRAPPER(_safe_type, _unsafe_type) \ 57 typedef union { _safe_type UNSAFE; } _unsafe_type \ 58 __attribute__((transparent_union)); \ 59 _Static_assert(sizeof(_safe_type) == sizeof(_unsafe_type), \ 60 "Size mismatch between unsafe and safe versions of a type") 61 #endif 62 63 VM_GENERATE_UNSAFE_WRAPPER(uint64_t, vm_addr_struct_t); 64 VM_GENERATE_UNSAFE_WRAPPER(uint64_t, vm_size_struct_t); 65 VM_GENERATE_UNSAFE_WRAPPER(uint32_t, vm32_addr_struct_t); 66 VM_GENERATE_UNSAFE_WRAPPER(uint32_t, vm32_size_struct_t); 67 68 /* 69 * Macros used to create a struct-wrapped type (called "unsafe" type) 70 * around a standard VM type. 71 */ 72 #if VM_UNSAFE_TYPES 73 #if defined(__cplusplus) 74 /* 75 * C++ doesn't support transparent_unions which fortunately isn't something 76 * we need, as files who need to see unsafe types as structs are all Code 77 */ 78 #error "Can't turn on unsafe types in C++" 79 #endif 80 81 #define VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) \ 82 VM_GENERATE_UNSAFE_WRAPPER(_safe_type, _unsafe_type) 83 84 #define VM_GENERATE_UNSAFE_BSD_TYPE(_safe_type, _unsafe_type) \ 85 VM_GENERATE_UNSAFE_WRAPPER(_safe_type, _unsafe_type) 86 87 /* 88 * Don't use this variant directly. Use VM_GENERATE_UNSAFE_ADDR or 89 * VM_GENERATE_UNSAFE_SIZE. 90 */ 91 #define VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, variant, size) \ 92 typedef vm ## size ## _ ## variant ## _struct_t _unsafe_type; \ 93 _Static_assert(sizeof(_safe_type) == sizeof(_unsafe_type), \ 94 "Size mismatch between unsafe and safe versions of a type") \ 95 96 #define VM_GENERATE_UNSAFE_BSD_EXT(_safe_type, _unsafe_type, variant, size) \ 97 typedef vm ## size ## _ ## variant ## _struct_t _unsafe_type; \ 98 _Static_assert(sizeof(_safe_type) == sizeof(_unsafe_type), \ 99 "Size mismatch between unsafe and safe versions of a type") 100 /* 101 * Use these variants for addresses and sizes as some types of addr/size 102 * are unsigned longs while others are unsigned long longs. Compiler 103 * is unhappy about conversions between unsafe pointers of the two. 104 */ 105 #define VM_GENERATE_UNSAFE_ADDR(_safe_type, _unsafe_type) \ 106 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, addr, ) 107 108 #define VM_GENERATE_UNSAFE_SIZE(_safe_type, _unsafe_type) \ 109 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, size, ) 110 111 #define VM_GENERATE_UNSAFE_BSD_ADDR(_safe_type, _unsafe_type) \ 112 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, addr, ) 113 114 #define VM_GENERATE_UNSAFE_BSD_SIZE(_safe_type, _unsafe_type) \ 115 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, size, ) 116 117 #define VM_GENERATE_UNSAFE_ADDR32(_safe_type, _unsafe_type) \ 118 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, addr, 32) 119 120 #define VM_GENERATE_UNSAFE_SIZE32(_safe_type, _unsafe_type) \ 121 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, size, 32) 122 123 #else /* VM_UNSAFE_TYPES */ 124 #define VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) \ 125 typedef _safe_type _unsafe_type 126 127 #define VM_GENERATE_UNSAFE_ADDR(_safe_type, _unsafe_type) \ 128 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 129 130 #define VM_GENERATE_UNSAFE_SIZE(_safe_type, _unsafe_type) \ 131 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 132 133 #define VM_GENERATE_UNSAFE_ADDR32(_safe_type, _unsafe_type) \ 134 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 135 136 #define VM_GENERATE_UNSAFE_SIZE32(_safe_type, _unsafe_type) \ 137 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 138 139 #endif /* VM_UNSAFE_TYPES */ 140 141 VM_GENERATE_UNSAFE_ADDR(mach_vm_address_t, mach_vm_address_ut); 142 VM_GENERATE_UNSAFE_ADDR(mach_vm_offset_t, mach_vm_offset_ut); 143 VM_GENERATE_UNSAFE_SIZE(mach_vm_size_t, mach_vm_size_ut); 144 145 VM_GENERATE_UNSAFE_ADDR(vm_address_t, vm_address_ut); 146 VM_GENERATE_UNSAFE_ADDR(vm_offset_t, vm_offset_ut); 147 VM_GENERATE_UNSAFE_SIZE(vm_size_t, vm_size_ut); 148 149 VM_GENERATE_UNSAFE_ADDR(vm_map_address_t, vm_map_address_ut); 150 VM_GENERATE_UNSAFE_ADDR(vm_map_offset_t, vm_map_offset_ut); 151 VM_GENERATE_UNSAFE_SIZE(vm_map_size_t, vm_map_size_ut); 152 153 VM_GENERATE_UNSAFE_ADDR(memory_object_offset_t, memory_object_offset_ut); 154 VM_GENERATE_UNSAFE_SIZE(memory_object_size_t, memory_object_size_ut); 155 156 VM_GENERATE_UNSAFE_ADDR(vm_object_offset_t, vm_object_offset_ut); 157 VM_GENERATE_UNSAFE_SIZE(vm_object_size_t, vm_object_size_ut); 158 159 #ifdef MACH_KERNEL_PRIVATE 160 VM_GENERATE_UNSAFE_ADDR32(vm32_address_t, vm32_address_ut); 161 VM_GENERATE_UNSAFE_ADDR32(vm32_offset_t, vm32_offset_ut); 162 VM_GENERATE_UNSAFE_SIZE32(vm32_size_t, vm32_size_ut); 163 #endif /* MACH_KERNEL_PRIVATE */ 164 165 VM_GENERATE_UNSAFE_TYPE(vm_prot_t, vm_prot_ut); 166 VM_GENERATE_UNSAFE_TYPE(vm_inherit_t, vm_inherit_ut); 167 168 #if VM_UNSAFE_TYPES 169 VM_GENERATE_UNSAFE_BSD_ADDR(caddr_t, caddr_ut); 170 VM_GENERATE_UNSAFE_BSD_ADDR(user_addr_t, user_addr_ut); 171 VM_GENERATE_UNSAFE_BSD_SIZE(size_t, size_ut); 172 VM_GENERATE_UNSAFE_BSD_SIZE(user_size_t, user_size_ut); 173 #endif /* VM_UNSAFE_TYPES */ 174 175 #endif /* _VM_UNSAFE_TYPES_H_ */ 176