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 C code 77 */ 78 #error "Can't turn on unsafe types in C++" 79 #endif 80 81 /* 82 * For defining a custom unsafe type that doesn't directly follow the 83 * transparent union model, and needs to be properly typedef'd outside of 84 * the VM subsystem. 85 */ 86 #define VM_DEFINE_UNSAFE_TYPE(_safe_type, _unsafe_type, _unsafe_contents) \ 87 typedef _unsafe_contents _unsafe_type; \ 88 _Static_assert( \ 89 ( \ 90 sizeof(_unsafe_type) \ 91 == sizeof(_safe_type)) \ 92 && ( \ 93 _Alignof(_unsafe_type) \ 94 == _Alignof(_safe_type)), \ 95 "Unsafe type should be compatible with corresponding safe type.") 96 97 #define VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) \ 98 VM_GENERATE_UNSAFE_WRAPPER(_safe_type, _unsafe_type) 99 100 #define VM_GENERATE_UNSAFE_BSD_TYPE(_safe_type, _unsafe_type) \ 101 VM_GENERATE_UNSAFE_WRAPPER(_safe_type, _unsafe_type) 102 103 /* 104 * Don't use this variant directly. Use VM_GENERATE_UNSAFE_ADDR or 105 * VM_GENERATE_UNSAFE_SIZE. 106 */ 107 #define VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, variant, size) \ 108 typedef vm ## size ## _ ## variant ## _struct_t _unsafe_type; \ 109 _Static_assert(sizeof(_safe_type) == sizeof(_unsafe_type), \ 110 "Size mismatch between unsafe and safe versions of a type") \ 111 112 #define VM_GENERATE_UNSAFE_BSD_EXT(_safe_type, _unsafe_type, variant, size) \ 113 typedef vm ## size ## _ ## variant ## _struct_t _unsafe_type; \ 114 _Static_assert(sizeof(_safe_type) == sizeof(_unsafe_type), \ 115 "Size mismatch between unsafe and safe versions of a type") 116 /* 117 * Use these variants for addresses and sizes as some types of addr/size 118 * are unsigned longs while others are unsigned long longs. Compiler 119 * is unhappy about conversions between unsafe pointers of the two. 120 */ 121 #define VM_GENERATE_UNSAFE_ADDR(_safe_type, _unsafe_type) \ 122 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, addr, ) 123 124 #define VM_GENERATE_UNSAFE_SIZE(_safe_type, _unsafe_type) \ 125 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, size, ) 126 127 #define VM_GENERATE_UNSAFE_BSD_ADDR(_safe_type, _unsafe_type) \ 128 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, addr, ) 129 130 #define VM_GENERATE_UNSAFE_BSD_SIZE(_safe_type, _unsafe_type) \ 131 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, size, ) 132 133 #define VM_GENERATE_UNSAFE_ADDR32(_safe_type, _unsafe_type) \ 134 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, addr, 32) 135 136 #define VM_GENERATE_UNSAFE_SIZE32(_safe_type, _unsafe_type) \ 137 VM_GENERATE_UNSAFE_EXT(_safe_type, _unsafe_type, size, 32) 138 139 #else /* VM_UNSAFE_TYPES */ 140 #define VM_DEFINE_UNSAFE_TYPE(_safe_type, _unsafe_type, _unsafe_contents) \ 141 typedef _safe_type _unsafe_type 142 143 #define VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) \ 144 VM_DEFINE_UNSAFE_TYPE(_safe_type, _unsafe_type, ) 145 146 #define VM_GENERATE_UNSAFE_ADDR(_safe_type, _unsafe_type) \ 147 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 148 149 #define VM_GENERATE_UNSAFE_SIZE(_safe_type, _unsafe_type) \ 150 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 151 152 #define VM_GENERATE_UNSAFE_ADDR32(_safe_type, _unsafe_type) \ 153 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 154 155 #define VM_GENERATE_UNSAFE_SIZE32(_safe_type, _unsafe_type) \ 156 VM_GENERATE_UNSAFE_TYPE(_safe_type, _unsafe_type) 157 158 #endif /* VM_UNSAFE_TYPES */ 159 160 VM_GENERATE_UNSAFE_ADDR(mach_vm_address_t, mach_vm_address_ut); 161 VM_GENERATE_UNSAFE_ADDR(mach_vm_offset_t, mach_vm_offset_ut); 162 VM_GENERATE_UNSAFE_SIZE(mach_vm_size_t, mach_vm_size_ut); 163 164 VM_GENERATE_UNSAFE_ADDR(vm_address_t, vm_address_ut); 165 VM_GENERATE_UNSAFE_ADDR(vm_offset_t, vm_offset_ut); 166 VM_GENERATE_UNSAFE_SIZE(vm_size_t, vm_size_ut); 167 168 VM_GENERATE_UNSAFE_ADDR(vm_map_address_t, vm_map_address_ut); 169 VM_GENERATE_UNSAFE_ADDR(vm_map_offset_t, vm_map_offset_ut); 170 VM_GENERATE_UNSAFE_SIZE(vm_map_size_t, vm_map_size_ut); 171 172 VM_GENERATE_UNSAFE_ADDR(memory_object_offset_t, memory_object_offset_ut); 173 VM_GENERATE_UNSAFE_SIZE(memory_object_size_t, memory_object_size_ut); 174 175 VM_GENERATE_UNSAFE_ADDR(vm_object_offset_t, vm_object_offset_ut); 176 VM_GENERATE_UNSAFE_SIZE(vm_object_size_t, vm_object_size_ut); 177 178 VM_GENERATE_UNSAFE_ADDR(pointer_t, pointer_ut); 179 180 #ifdef MACH_KERNEL_PRIVATE 181 VM_GENERATE_UNSAFE_ADDR32(vm32_address_t, vm32_address_ut); 182 VM_GENERATE_UNSAFE_ADDR32(vm32_offset_t, vm32_offset_ut); 183 VM_GENERATE_UNSAFE_SIZE32(vm32_size_t, vm32_size_ut); 184 #endif /* MACH_KERNEL_PRIVATE */ 185 186 VM_GENERATE_UNSAFE_TYPE(vm_prot_t, vm_prot_ut); 187 VM_GENERATE_UNSAFE_TYPE(vm_inherit_t, vm_inherit_ut); 188 VM_GENERATE_UNSAFE_TYPE(vm_behavior_t, vm_behavior_ut); 189 190 #if VM_UNSAFE_TYPES 191 VM_GENERATE_UNSAFE_BSD_ADDR(caddr_t, caddr_ut); 192 VM_GENERATE_UNSAFE_BSD_ADDR(user_addr_t, user_addr_ut); 193 VM_GENERATE_UNSAFE_BSD_SIZE(size_t, size_ut); 194 VM_GENERATE_UNSAFE_BSD_SIZE(user_size_t, user_size_ut); 195 #endif /* VM_UNSAFE_TYPES */ 196 197 VM_DEFINE_UNSAFE_TYPE(struct mach_vm_range, mach_vm_range_ut, struct { 198 mach_vm_offset_ut min_address_u; 199 mach_vm_offset_ut max_address_u; 200 }); 201 202 #pragma pack(1) 203 204 VM_DEFINE_UNSAFE_TYPE(mach_vm_range_recipe_v1_t, mach_vm_range_recipe_v1_ut, struct { 205 mach_vm_range_flags_t flags: 48; 206 mach_vm_range_tag_t range_tag: 8; 207 uint8_t vm_tag: 8; 208 mach_vm_range_ut range_u; 209 }); 210 211 #pragma pack() 212 213 #endif /* _VM_UNSAFE_TYPES_H_ */ 214