xref: /xnu-11215.1.10/osfmk/mach/vm_types_unsafe.h (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
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