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