xref: /xnu-10063.141.1/osfmk/vm/vm_shared_region.h (revision d8b80295118ef25ac3a784134bcf95cd8e88109f) !
1 /*
2  * Copyright (c) 2007 Apple Inc. All rights reserved.
3  *
4  * @APPLE_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. Please obtain a copy of the License at
10  * http://www.opensource.apple.com/apsl/ and read it before using this
11  * file.
12  *
13  * The Original Code and all software distributed under the License are
14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18  * Please see the License for the specific language governing rights and
19  * limitations under the License.
20  *
21  * @APPLE_LICENSE_HEADER_END@
22  */
23 /*
24  *
25  *	File: vm/vm_shared_region.h
26  *
27  *      protos and struct definitions for shared region
28  */
29 
30 #ifndef _VM_SHARED_REGION_H_
31 #define _VM_SHARED_REGION_H_
32 
33 #ifdef  KERNEL_PRIVATE
34 
35 #include <mach/vm_prot.h>
36 #include <mach/mach_types.h>
37 #include <mach/shared_region.h>
38 
39 #include <kern/kern_types.h>
40 #include <kern/macro_help.h>
41 
42 #include <vm/vm_map.h>
43 
44 extern int shared_region_version;
45 extern int shared_region_persistence;
46 
47 #if DEBUG
48 extern int shared_region_debug;
49 #define SHARED_REGION_DEBUG(args)               \
50 	MACRO_BEGIN                             \
51 	if (shared_region_debug) {              \
52 	        kprintf args;                   \
53 	}                                       \
54 	MACRO_END
55 #else /* DEBUG */
56 #define SHARED_REGION_DEBUG(args)
57 #endif /* DEBUG */
58 
59 extern int shared_region_trace_level;
60 
61 extern struct vm_shared_region *primary_system_shared_region;
62 
63 #define SHARED_REGION_TRACE_NONE_LVL            0 /* no trace */
64 #define SHARED_REGION_TRACE_ERROR_LVL           1 /* trace abnormal events */
65 #define SHARED_REGION_TRACE_INFO_LVL            2 /* trace all events */
66 #define SHARED_REGION_TRACE_DEBUG_LVL           3 /* extra traces for debug */
67 #define SHARED_REGION_TRACE(level, args)                \
68 	MACRO_BEGIN                                     \
69 	if (shared_region_trace_level >= level) {       \
70 	        printf args;                            \
71 	}                                               \
72 	MACRO_END
73 #define SHARED_REGION_TRACE_NONE(args)
74 #define SHARED_REGION_TRACE_ERROR(args)                         \
75 	MACRO_BEGIN                                             \
76 	SHARED_REGION_TRACE(SHARED_REGION_TRACE_ERROR_LVL,      \
77 	                    args);                              \
78 	MACRO_END
79 #define SHARED_REGION_TRACE_INFO(args)                          \
80 	MACRO_BEGIN                                             \
81 	SHARED_REGION_TRACE(SHARED_REGION_TRACE_INFO_LVL,       \
82 	                    args);                              \
83 	MACRO_END
84 #define SHARED_REGION_TRACE_DEBUG(args)                         \
85 	MACRO_BEGIN                                             \
86 	SHARED_REGION_TRACE(SHARED_REGION_TRACE_DEBUG_LVL,      \
87 	                    args);                              \
88 	MACRO_END
89 
90 typedef struct vm_shared_region *vm_shared_region_t;
91 
92 #ifdef MACH_KERNEL_PRIVATE
93 
94 #include <kern/queue.h>
95 #include <vm/vm_object.h>
96 #include <vm/memory_object.h>
97 
98 #define PAGE_SIZE_FOR_SR_SLIDE          4096
99 #define PAGE_SIZE_FOR_SR_SLIDE_16KB     16384
100 
101 /*
102  * Documentation for the slide info format can be found in the dyld project in
103  * the file 'launch-cache/dyld_cache_format.h'.
104  */
105 
106 typedef struct vm_shared_region_slide_info_entry_v1 *vm_shared_region_slide_info_entry_v1_t;
107 struct vm_shared_region_slide_info_entry_v1 {
108 	uint32_t        version;
109 	uint32_t        toc_offset;     // offset from start of header to table-of-contents
110 	uint32_t        toc_count;      // number of entries in toc (same as number of pages in r/w mapping)
111 	uint32_t        entry_offset;
112 	uint32_t        entry_count;
113 	uint32_t        entries_size;
114 	// uint16_t	toc[toc_count];
115 	// entrybitmap	entries[entries_count];
116 };
117 
118 #define NUM_SLIDING_BITMAPS_PER_PAGE    (0x1000/sizeof(int)/8) /*128*/
119 typedef struct slide_info_entry_toc     *slide_info_entry_toc_t;
120 struct slide_info_entry_toc {
121 	uint8_t entry[NUM_SLIDING_BITMAPS_PER_PAGE];
122 };
123 
124 typedef struct vm_shared_region_slide_info_entry_v2 *vm_shared_region_slide_info_entry_v2_t;
125 struct vm_shared_region_slide_info_entry_v2 {
126 	uint32_t        version;
127 	uint32_t        page_size;
128 	uint32_t        page_starts_offset;
129 	uint32_t        page_starts_count;
130 	uint32_t        page_extras_offset;
131 	uint32_t        page_extras_count;
132 	uint64_t        delta_mask;             // which (contiguous) set of bits contains the delta to the next rebase location
133 	uint64_t        value_add;
134 	// uint16_t	page_starts[page_starts_count];
135 	// uint16_t	page_extras[page_extras_count];
136 };
137 
138 #define DYLD_CACHE_SLIDE_PAGE_ATTRS             0xC000  // high bits of uint16_t are flags
139 #define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA        0x8000  // index is into extras array (not starts array)
140 #define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE    0x4000  // page has no rebasing
141 #define DYLD_CACHE_SLIDE_PAGE_ATTR_END          0x8000  // last chain entry for page
142 #define DYLD_CACHE_SLIDE_PAGE_VALUE             0x3FFF  // bitwise negation of DYLD_CACHE_SLIDE_PAGE_ATTRS
143 #define DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT      2
144 
145 typedef struct vm_shared_region_slide_info_entry_v3 *vm_shared_region_slide_info_entry_v3_t;
146 struct vm_shared_region_slide_info_entry_v3 {
147 	uint32_t        version;                        // currently 3
148 	uint32_t        page_size;                      // currently 4096 (may also be 16384)
149 	uint32_t        page_starts_count;
150 	uint64_t        value_add;
151 	uint16_t        page_starts[] /* page_starts_count */;
152 };
153 
154 #define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF  // page has no rebasing
155 
156 
157 typedef struct vm_shared_region_slide_info_entry_v4 *vm_shared_region_slide_info_entry_v4_t;
158 struct vm_shared_region_slide_info_entry_v4 {
159 	uint32_t    version;        // currently 4
160 	uint32_t    page_size;      // currently 4096 (may also be 16384)
161 	uint32_t    page_starts_offset;
162 	uint32_t    page_starts_count;
163 	uint32_t    page_extras_offset;
164 	uint32_t    page_extras_count;
165 	uint64_t    delta_mask;    // which (contiguous) set of bits contains the delta to the next rebase location (0xC0000000)
166 	uint64_t    value_add;     // base address of cache
167 	// uint16_t    page_starts[page_starts_count];
168 	// uint16_t    page_extras[page_extras_count];
169 };
170 
171 #define DYLD_CACHE_SLIDE4_PAGE_NO_REBASE           0xFFFF  // page has no rebasing
172 #define DYLD_CACHE_SLIDE4_PAGE_INDEX               0x7FFF  // index into starts or extras
173 #define DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA           0x8000  // index is into extras array (not starts array)
174 #define DYLD_CACHE_SLIDE4_PAGE_EXTRA_END           0x8000  // last chain entry for page
175 
176 
177 typedef struct vm_shared_region_slide_info_entry_v5 *vm_shared_region_slide_info_entry_v5_t;
178 struct vm_shared_region_slide_info_entry_v5 {
179 	uint32_t    version;        // currently 5
180 	uint32_t    page_size;      // 16384
181 	uint32_t    page_starts_count;
182 	uint64_t    value_add;
183 	uint16_t    page_starts[] /* page_starts_count */;
184 };
185 
186 #define DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE    0xFFFF    // page has no rebasing
187 
188 
189 typedef union vm_shared_region_slide_info_entry *vm_shared_region_slide_info_entry_t;
190 union vm_shared_region_slide_info_entry {
191 	struct {
192 		uint32_t version;
193 		uint32_t page_size; // only valid to use this on version >= 2
194 	};
195 	struct vm_shared_region_slide_info_entry_v1 v1;
196 	struct vm_shared_region_slide_info_entry_v2 v2;
197 	struct vm_shared_region_slide_info_entry_v3 v3;
198 	struct vm_shared_region_slide_info_entry_v4 v4;
199 	struct vm_shared_region_slide_info_entry_v5 v5;
200 };
201 
202 #define MIN_SLIDE_INFO_SIZE \
203     MIN(sizeof(struct vm_shared_region_slide_info_entry_v1), \
204     MIN(sizeof(struct vm_shared_region_slide_info_entry_v2), \
205     MIN(sizeof(struct vm_shared_region_slide_info_entry_v3), \
206     MIN(sizeof(struct vm_shared_region_slide_info_entry_v4), \
207     sizeof(struct vm_shared_region_slide_info_entry_v5)))))
208 
209 /*
210  * This is the information used by the shared cache pager for sub-sections
211  * which must be modified for relocations and/or pointer authentications
212  * before it can be used. The shared_region_pager gets source pages from
213  * the shared cache file and modifies them -- see shared_region_pager_data_request().
214  *
215  * A single pager may be used from multiple shared regions provided:
216  * - same si_slide_object, si_start, si_end, si_slide, si_ptrauth and si_jop_key
217  * - The size and contents of si_slide_info_entry are the same.
218  */
219 typedef struct vm_shared_region_slide_info {
220 	uint32_t                si_slide;           /* the distance that the file data is relocated */
221 	bool                    si_slid;
222 #if __has_feature(ptrauth_calls)
223 	bool                    si_ptrauth;
224 	uint64_t                si_jop_key;
225 	struct vm_shared_region *si_shared_region; /* so we can ref/dealloc for authenticated slide info */
226 #endif /* __has_feature(ptrauth_calls) */
227 	mach_vm_address_t       si_slid_address __kernel_data_semantics;
228 	mach_vm_offset_t        si_start __kernel_data_semantics; /* start offset in si_slide_object */
229 	mach_vm_offset_t        si_end __kernel_data_semantics;
230 	vm_object_t             si_slide_object;    /* The source object for the pages to be modified */
231 	mach_vm_size_t          si_slide_info_size; /* size of dyld provided relocation information */
232 	vm_shared_region_slide_info_entry_t si_slide_info_entry; /* dyld provided relocation information */
233 } *vm_shared_region_slide_info_t;
234 
235 /*
236  * Data structure that represents a unique shared cache region.
237  */
238 struct vm_shared_region {
239 	uint32_t                sr_ref_count;
240 	uint32_t                sr_slide;
241 	queue_chain_t           sr_q;
242 	void                    *sr_root_dir;
243 	cpu_type_t              sr_cpu_type;
244 	cpu_subtype_t           sr_cpu_subtype;
245 	ipc_port_t              sr_mem_entry;
246 	mach_vm_offset_t        sr_first_mapping;
247 	mach_vm_offset_t        sr_base_address;
248 	mach_vm_size_t          sr_size;
249 	mach_vm_offset_t        sr_pmap_nesting_start;
250 	mach_vm_size_t          sr_pmap_nesting_size;
251 	thread_call_t           sr_timer_call;
252 	uuid_t                  sr_uuid;
253 
254 #if __ARM_MIXED_PAGE_SIZE__
255 	uint8_t                 sr_page_shift;
256 #endif /* __ARM_MIXED_PAGE_SIZE__ */
257 	thread_t                sr_mapping_in_progress; /* sr_first_mapping will be != -1 when done */
258 	thread_t                sr_slide_in_progress;
259 	bool                    sr_64bit;
260 	bool                    sr_persists;
261 	bool                    sr_uuid_copied;
262 	bool                    sr_stale;              /* This region should never be used again. */
263 	bool                    sr_driverkit;
264 
265 #if __has_feature(ptrauth_calls)
266 	bool                    sr_reslide;            /* Special shared region for suspected attacked processes */
267 	uint_t                  sr_num_auth_section;  /* num entries in sr_auth_section */
268 	uint_t                  sr_next_auth_section; /* used while filling in sr_auth_section */
269 	vm_shared_region_slide_info_t *sr_auth_section;
270 #endif /* __has_feature(ptrauth_calls) */
271 
272 	uint32_t                sr_rsr_version;
273 
274 	uint64_t                sr_install_time; /* mach_absolute_time() of installation into global list */
275 	uint32_t                sr_id; /* identifier for shared cache */
276 	uint32_t                sr_images_count;
277 	struct dyld_uuid_info_64 *sr_images;
278 };
279 
280 extern kern_return_t vm_shared_region_slide_page(
281 	vm_shared_region_slide_info_t si,
282 	vm_offset_t                   vaddr,
283 	mach_vm_offset_t              uservaddr,
284 	uint32_t                      pageIndex,
285 	uint64_t                      jop_key);
286 extern uint64_t shared_region_find_key(char *shared_region_id);
287 #else  /* !MACH_KERNEL_PRIVATE */
288 
289 struct vm_shared_region;
290 struct vm_shared_region_slide_info;
291 struct vm_shared_region_slide_info_entry;
292 struct slide_info_entry_toc;
293 
294 #endif /* MACH_KERNEL_PRIVATE */
295 
296 struct _sr_file_mappings {
297 	int                     fd;
298 	uint32_t                mappings_count;
299 	struct shared_file_mapping_slide_np *mappings;
300 	uint32_t                slide;
301 	struct fileproc         *fp;
302 	struct vnode            *vp;
303 	memory_object_size_t    file_size;
304 	memory_object_control_t file_control;
305 };
306 
307 extern void vm_shared_region_init(void);
308 extern kern_return_t vm_shared_region_enter(
309 	struct _vm_map          *map,
310 	struct task             *task,
311 	boolean_t               is_64bit,
312 	void                    *fsroot,
313 	cpu_type_t              cpu,
314 	cpu_subtype_t           cpu_subtype,
315 	boolean_t               reslide,
316 	boolean_t               is_driverkit,
317 	uint32_t                rsr_version);
318 extern void vm_shared_region_remove(
319 	struct task             *task,
320 	struct vm_shared_region *sr);
321 extern vm_shared_region_t vm_shared_region_get(
322 	struct task             *task);
323 extern vm_shared_region_t vm_shared_region_trim_and_get(
324 	struct task             *task);
325 extern void vm_shared_region_deallocate(
326 	struct vm_shared_region *shared_region);
327 extern vm_map_t vm_shared_region_vm_map(
328 	struct vm_shared_region *shared_region);
329 extern void vm_shared_region_set(
330 	struct task             *task,
331 	struct vm_shared_region *new_shared_region);
332 extern vm_shared_region_t vm_shared_region_lookup(
333 	void                    *root_dir,
334 	cpu_type_t              cpu,
335 	cpu_subtype_t           cpu_subtype,
336 	boolean_t               is_64bit,
337 	int                     target_page_shift,
338 	boolean_t               reslide,
339 	boolean_t               is_driverkit,
340 	uint32_t                rsr_version);
341 extern kern_return_t vm_shared_region_start_address(
342 	struct vm_shared_region *shared_region,
343 	mach_vm_offset_t        *start_address,
344 	task_t                  task);
345 extern void vm_shared_region_undo_mappings(
346 	vm_map_t sr_map,
347 	mach_vm_offset_t sr_base_address,
348 	struct _sr_file_mappings *srf_mappings,
349 	struct _sr_file_mappings *srf_mappings_count,
350 	unsigned int mappings_count);
351 __attribute__((noinline))
352 extern kern_return_t vm_shared_region_map_file(
353 	struct vm_shared_region *shared_region,
354 	int                     sr_mappings_count,
355 	struct _sr_file_mappings *sr_mappings);
356 extern void *vm_shared_region_root_dir(
357 	struct vm_shared_region *shared_region);
358 extern kern_return_t vm_shared_region_sliding_valid(uint32_t slide);
359 extern void vm_commpage_init(void);
360 extern void vm_commpage_text_init(void);
361 extern kern_return_t vm_commpage_enter(
362 	struct _vm_map          *map,
363 	struct task             *task,
364 	boolean_t               is64bit);
365 extern kern_return_t vm_commpage_remove(
366 	struct _vm_map          *map,
367 	struct task             *task);
368 int vm_shared_region_slide(uint32_t,
369     mach_vm_offset_t,
370     mach_vm_size_t,
371     mach_vm_offset_t,
372     mach_vm_size_t,
373     mach_vm_offset_t,
374     memory_object_control_t,
375     vm_prot_t);
376 extern void vm_shared_region_pivot(void);
377 extern void vm_shared_region_reslide_stale(boolean_t driverkit);
378 #if __has_feature(ptrauth_calls)
379 __attribute__((noinline))
380 extern kern_return_t vm_shared_region_auth_remap(vm_shared_region_t sr);
381 #endif /* __has_feature(ptrauth_calls) */
382 extern void vm_shared_region_reference(vm_shared_region_t sr);
383 
384 #endif /* KERNEL_PRIVATE */
385 
386 #endif  /* _VM_SHARED_REGION_H_ */
387