xref: /xnu-12377.61.12/osfmk/vm/vm_shared_region_xnu.h (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
1 /*
2  * Copyright (c) 2023 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_SHARED_REGION_XNU_H_
30 #define _VM_SHARED_REGION_XNU_H_
31 
32 #include <sys/cdefs.h>
33 #include <vm/vm_shared_region.h>
34 
35 __BEGIN_DECLS
36 
37 #ifdef MACH_KERNEL_PRIVATE
38 
39 #include <kern/queue.h>
40 #include <vm/vm_object_xnu.h>
41 #include <vm/memory_object.h>
42 
43 #define PAGE_SIZE_FOR_SR_SLIDE          4096
44 #define PAGE_SIZE_FOR_SR_SLIDE_16KB     16384
45 
46 /*
47  * Documentation for the slide info format can be found in the dyld project in
48  * the file 'launch-cache/dyld_cache_format.h'.
49  */
50 
51 typedef struct vm_shared_region_slide_info_entry_v1 *vm_shared_region_slide_info_entry_v1_t;
52 struct vm_shared_region_slide_info_entry_v1 {
53 	uint32_t        version;
54 	uint32_t        toc_offset;     // offset from start of header to table-of-contents
55 	uint32_t        toc_count;      // number of entries in toc (same as number of pages in r/w mapping)
56 	uint32_t        entry_offset;
57 	uint32_t        entry_count;
58 	uint32_t        entries_size;
59 	// uint16_t	toc[toc_count];
60 	// entrybitmap	entries[entries_count];
61 };
62 
63 #define NUM_SLIDING_BITMAPS_PER_PAGE    (0x1000/sizeof(int)/8) /*128*/
64 typedef struct slide_info_entry_toc     *slide_info_entry_toc_t;
65 struct slide_info_entry_toc {
66 	uint8_t entry[NUM_SLIDING_BITMAPS_PER_PAGE];
67 };
68 
69 typedef struct vm_shared_region_slide_info_entry_v2 *vm_shared_region_slide_info_entry_v2_t;
70 struct vm_shared_region_slide_info_entry_v2 {
71 	uint32_t        version;
72 	uint32_t        page_size;
73 	uint32_t        page_starts_offset;
74 	uint32_t        page_starts_count;
75 	uint32_t        page_extras_offset;
76 	uint32_t        page_extras_count;
77 	uint64_t        delta_mask;             // which (contiguous) set of bits contains the delta to the next rebase location
78 	uint64_t        value_add;
79 	// uint16_t	page_starts[page_starts_count];
80 	// uint16_t	page_extras[page_extras_count];
81 };
82 
83 #define DYLD_CACHE_SLIDE_PAGE_ATTRS             0xC000  // high bits of uint16_t are flags
84 #define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA        0x8000  // index is into extras array (not starts array)
85 #define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE    0x4000  // page has no rebasing
86 #define DYLD_CACHE_SLIDE_PAGE_ATTR_END          0x8000  // last chain entry for page
87 #define DYLD_CACHE_SLIDE_PAGE_VALUE             0x3FFF  // bitwise negation of DYLD_CACHE_SLIDE_PAGE_ATTRS
88 #define DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT      2
89 
90 typedef struct vm_shared_region_slide_info_entry_v3 *vm_shared_region_slide_info_entry_v3_t;
91 struct vm_shared_region_slide_info_entry_v3 {
92 	uint32_t        version;                        // currently 3
93 	uint32_t        page_size;                      // currently 4096 (may also be 16384)
94 	uint32_t        page_starts_count;
95 	uint64_t        value_add;
96 	uint16_t        page_starts[] /* page_starts_count */;
97 };
98 
99 #define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF  // page has no rebasing
100 
101 
102 typedef struct vm_shared_region_slide_info_entry_v4 *vm_shared_region_slide_info_entry_v4_t;
103 struct vm_shared_region_slide_info_entry_v4 {
104 	uint32_t    version;        // currently 4
105 	uint32_t    page_size;      // currently 4096 (may also be 16384)
106 	uint32_t    page_starts_offset;
107 	uint32_t    page_starts_count;
108 	uint32_t    page_extras_offset;
109 	uint32_t    page_extras_count;
110 	uint64_t    delta_mask;    // which (contiguous) set of bits contains the delta to the next rebase location (0xC0000000)
111 	uint64_t    value_add;     // base address of cache
112 	// uint16_t    page_starts[page_starts_count];
113 	// uint16_t    page_extras[page_extras_count];
114 };
115 
116 #define DYLD_CACHE_SLIDE4_PAGE_NO_REBASE           0xFFFF  // page has no rebasing
117 #define DYLD_CACHE_SLIDE4_PAGE_INDEX               0x7FFF  // index into starts or extras
118 #define DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA           0x8000  // index is into extras array (not starts array)
119 #define DYLD_CACHE_SLIDE4_PAGE_EXTRA_END           0x8000  // last chain entry for page
120 
121 
122 typedef struct vm_shared_region_slide_info_entry_v5 *vm_shared_region_slide_info_entry_v5_t;
123 struct vm_shared_region_slide_info_entry_v5 {
124 	uint32_t    version;        // currently 5
125 	uint32_t    page_size;      // 16384
126 	uint32_t    page_starts_count;
127 	uint64_t    value_add;
128 	uint16_t    page_starts[] /* page_starts_count */;
129 };
130 
131 #define DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE    0xFFFF    // page has no rebasing
132 
133 
134 typedef union vm_shared_region_slide_info_entry *vm_shared_region_slide_info_entry_t;
135 union vm_shared_region_slide_info_entry {
136 	struct {
137 		uint32_t version;
138 		uint32_t page_size; // only valid to use this on version >= 2
139 	};
140 	struct vm_shared_region_slide_info_entry_v1 v1;
141 	struct vm_shared_region_slide_info_entry_v2 v2;
142 	struct vm_shared_region_slide_info_entry_v3 v3;
143 	struct vm_shared_region_slide_info_entry_v4 v4;
144 	struct vm_shared_region_slide_info_entry_v5 v5;
145 };
146 
147 #define MIN_SLIDE_INFO_SIZE \
148     MIN(sizeof(struct vm_shared_region_slide_info_entry_v1), \
149     MIN(sizeof(struct vm_shared_region_slide_info_entry_v2), \
150     MIN(sizeof(struct vm_shared_region_slide_info_entry_v3), \
151     MIN(sizeof(struct vm_shared_region_slide_info_entry_v4), \
152     sizeof(struct vm_shared_region_slide_info_entry_v5)))))
153 
154 /*
155  * This is the information used by the shared cache pager for sub-sections
156  * which must be modified for relocations and/or pointer authentications
157  * before it can be used. The shared_region_pager gets source pages from
158  * the shared cache file and modifies them -- see shared_region_pager_data_request().
159  *
160  * A single pager may be used from multiple shared regions provided:
161  * - same si_slide_object, si_start, si_end, si_slide, si_ptrauth and si_jop_key
162  * - The size and contents of si_slide_info_entry are the same.
163  */
164 typedef struct vm_shared_region_slide_info {
165 	uint32_t                si_slide;           /* the distance that the file data is relocated */
166 	bool                    si_slid;
167 #if __has_feature(ptrauth_calls)
168 	bool                    si_ptrauth;
169 	uint64_t                si_jop_key;
170 	struct vm_shared_region *si_shared_region; /* so we can ref/dealloc for authenticated slide info */
171 #endif /* __has_feature(ptrauth_calls) */
172 	mach_vm_address_t       si_slid_address __kernel_data_semantics;
173 	mach_vm_offset_t        si_start __kernel_data_semantics; /* start offset in si_slide_object */
174 	mach_vm_offset_t        si_end __kernel_data_semantics;
175 	vm_object_t             si_slide_object;    /* The source object for the pages to be modified */
176 	mach_vm_size_t          si_slide_info_size; /* size of dyld provided relocation information */
177 	vm_shared_region_slide_info_entry_t si_slide_info_entry; /* dyld provided relocation information */
178 } *vm_shared_region_slide_info_t;
179 
180 /*
181  * Data structure that represents a unique shared cache region.
182  */
183 struct vm_shared_region {
184 	uint32_t                sr_ref_count;
185 	uint32_t                sr_slide;
186 	queue_chain_t           sr_q;
187 	void                    *sr_root_dir;
188 	cpu_type_t              sr_cpu_type;
189 	cpu_subtype_t           sr_cpu_subtype;
190 	ipc_port_t              sr_mem_entry;
191 	vm_map_t                sr_config_map;
192 	mach_vm_offset_t        sr_first_mapping;
193 	mach_vm_offset_t        sr_base_address;
194 	mach_vm_size_t          sr_size;
195 	mach_vm_offset_t        sr_pmap_nesting_start;
196 	mach_vm_size_t          sr_pmap_nesting_size;
197 	thread_call_t           sr_timer_call;
198 	uuid_t                  sr_uuid;
199 
200 #if __ARM_MIXED_PAGE_SIZE__
201 	uint8_t                 sr_page_shift;
202 #endif /* __ARM_MIXED_PAGE_SIZE__ */
203 	thread_t                sr_mapping_in_progress; /* sr_first_mapping will be != -1 when done */
204 	thread_t                sr_slide_in_progress;
205 	bool                    sr_64bit;
206 	bool                    sr_persists;
207 	bool                    sr_uuid_copied;
208 	bool                    sr_stale;              /* This region should never be used again. */
209 	bool                    sr_driverkit;
210 
211 #if __has_feature(ptrauth_calls)
212 	bool                    sr_reslide;            /* Special shared region for suspected attacked processes */
213 	uint_t                  sr_num_auth_section;  /* num entries in sr_auth_section */
214 	uint_t                  sr_next_auth_section; /* used while filling in sr_auth_section */
215 	vm_shared_region_slide_info_t *sr_auth_section;
216 #endif /* __has_feature(ptrauth_calls) */
217 
218 	uint32_t                sr_rsr_version;
219 
220 	uint64_t                sr_install_time; /* mach_absolute_time() of installation into global list */
221 	uint32_t                sr_id; /* identifier for shared cache */
222 	uint32_t                sr_images_count;
223 	struct dyld_uuid_info_64 *sr_images;
224 };
225 
226 extern uint64_t shared_region_find_key(char *shared_region_id);
227 
228 #endif /* MACH_KERNEL_PRIVATE */
229 
230 #ifdef XNU_KERNEL_PRIVATE
231 
232 extern vm_shared_region_t vm_shared_region_get(
233 	struct task             *task);
234 extern void vm_shared_region_deallocate(
235 	struct vm_shared_region *shared_region);
236 extern void vm_shared_region_set(
237 	struct task             *task,
238 	struct vm_shared_region *new_shared_region);
239 extern kern_return_t vm_shared_region_sliding_valid(uint32_t slide);
240 extern void vm_commpage_init(void);
241 extern void vm_commpage_text_init(void);
242 extern void vm_shared_region_reslide_stale(boolean_t driverkit);
243 extern kern_return_t vm_shared_region_update_task(
244 	struct task *task,
245 	struct vm_shared_region *shared_region,
246 	mach_vm_offset_t start_address);
247 #endif /* XNU_KERNEL_PRIVATE */
248 
249 __END_DECLS
250 
251 #endif  /* _VM_SHARED_REGION_XNU_H_ */
252