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