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 100 /* 101 * Documentation for the slide info format can be found in the dyld project in 102 * the file 'launch-cache/dyld_cache_format.h'. 103 */ 104 105 typedef struct vm_shared_region_slide_info_entry_v1 *vm_shared_region_slide_info_entry_v1_t; 106 struct vm_shared_region_slide_info_entry_v1 { 107 uint32_t version; 108 uint32_t toc_offset; // offset from start of header to table-of-contents 109 uint32_t toc_count; // number of entries in toc (same as number of pages in r/w mapping) 110 uint32_t entry_offset; 111 uint32_t entry_count; 112 uint32_t entries_size; 113 // uint16_t toc[toc_count]; 114 // entrybitmap entries[entries_count]; 115 }; 116 117 #define NUM_SLIDING_BITMAPS_PER_PAGE (0x1000/sizeof(int)/8) /*128*/ 118 typedef struct slide_info_entry_toc *slide_info_entry_toc_t; 119 struct slide_info_entry_toc { 120 uint8_t entry[NUM_SLIDING_BITMAPS_PER_PAGE]; 121 }; 122 123 typedef struct vm_shared_region_slide_info_entry_v2 *vm_shared_region_slide_info_entry_v2_t; 124 struct vm_shared_region_slide_info_entry_v2 { 125 uint32_t version; 126 uint32_t page_size; 127 uint32_t page_starts_offset; 128 uint32_t page_starts_count; 129 uint32_t page_extras_offset; 130 uint32_t page_extras_count; 131 uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location 132 uint64_t value_add; 133 // uint16_t page_starts[page_starts_count]; 134 // uint16_t page_extras[page_extras_count]; 135 }; 136 137 #define DYLD_CACHE_SLIDE_PAGE_ATTRS 0xC000 // high bits of uint16_t are flags 138 #define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA 0x8000 // index is into extras array (not starts array) 139 #define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE 0x4000 // page has no rebasing 140 #define DYLD_CACHE_SLIDE_PAGE_ATTR_END 0x8000 // last chain entry for page 141 #define DYLD_CACHE_SLIDE_PAGE_VALUE 0x3FFF // bitwise negation of DYLD_CACHE_SLIDE_PAGE_ATTRS 142 #define DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT 2 143 144 typedef struct vm_shared_region_slide_info_entry_v3 *vm_shared_region_slide_info_entry_v3_t; 145 struct vm_shared_region_slide_info_entry_v3 { 146 uint32_t version; // currently 3 147 uint32_t page_size; // currently 4096 (may also be 16384) 148 uint32_t page_starts_count; 149 uint64_t value_add; 150 uint16_t page_starts[] /* page_starts_count */; 151 }; 152 153 #define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF // page has no rebasing 154 155 156 typedef struct vm_shared_region_slide_info_entry_v4 *vm_shared_region_slide_info_entry_v4_t; 157 struct vm_shared_region_slide_info_entry_v4 { 158 uint32_t version; // currently 4 159 uint32_t page_size; // currently 4096 (may also be 16384) 160 uint32_t page_starts_offset; 161 uint32_t page_starts_count; 162 uint32_t page_extras_offset; 163 uint32_t page_extras_count; 164 uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location (0xC0000000) 165 uint64_t value_add; // base address of cache 166 // uint16_t page_starts[page_starts_count]; 167 // uint16_t page_extras[page_extras_count]; 168 }; 169 170 #define DYLD_CACHE_SLIDE4_PAGE_NO_REBASE 0xFFFF // page has no rebasing 171 #define DYLD_CACHE_SLIDE4_PAGE_INDEX 0x7FFF // index into starts or extras 172 #define DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA 0x8000 // index is into extras array (not starts array) 173 #define DYLD_CACHE_SLIDE4_PAGE_EXTRA_END 0x8000 // last chain entry for page 174 175 176 177 typedef union vm_shared_region_slide_info_entry *vm_shared_region_slide_info_entry_t; 178 union vm_shared_region_slide_info_entry { 179 uint32_t version; 180 struct vm_shared_region_slide_info_entry_v1 v1; 181 struct vm_shared_region_slide_info_entry_v2 v2; 182 struct vm_shared_region_slide_info_entry_v3 v3; 183 struct vm_shared_region_slide_info_entry_v4 v4; 184 }; 185 186 #define MIN_SLIDE_INFO_SIZE \ 187 MIN(sizeof(struct vm_shared_region_slide_info_entry_v1), \ 188 MIN(sizeof(struct vm_shared_region_slide_info_entry_v2), \ 189 MIN(sizeof(struct vm_shared_region_slide_info_entry_v3), \ 190 sizeof(struct vm_shared_region_slide_info_entry_v4)))) 191 192 /* 193 * This is the information used by the shared cache pager for sub-sections 194 * which must be modified for relocations and/or pointer authentications 195 * before it can be used. The shared_region_pager gets source pages from 196 * the shared cache file and modifies them -- see shared_region_pager_data_request(). 197 * 198 * A single pager may be used from multiple shared regions provided: 199 * - same si_slide_object, si_start, si_end, si_slide, si_ptrauth and si_jop_key 200 * - The size and contents of si_slide_info_entry are the same. 201 */ 202 typedef struct vm_shared_region_slide_info { 203 uint32_t si_slide; /* the distance that the file data is relocated */ 204 bool si_slid; 205 #if __has_feature(ptrauth_calls) 206 bool si_ptrauth; 207 uint64_t si_jop_key; 208 struct vm_shared_region *si_shared_region; /* so we can ref/dealloc for authenticated slide info */ 209 #endif /* __has_feature(ptrauth_calls) */ 210 mach_vm_address_t si_slid_address __kernel_data_semantics; 211 mach_vm_offset_t si_start __kernel_data_semantics; /* start offset in si_slide_object */ 212 mach_vm_offset_t si_end __kernel_data_semantics; 213 vm_object_t si_slide_object; /* The source object for the pages to be modified */ 214 mach_vm_size_t si_slide_info_size; /* size of dyld provided relocation information */ 215 vm_shared_region_slide_info_entry_t si_slide_info_entry; /* dyld provided relocation information */ 216 } *vm_shared_region_slide_info_t; 217 218 /* 219 * Data structure that represents a unique shared cache region. 220 */ 221 struct vm_shared_region { 222 uint32_t sr_ref_count; 223 uint32_t sr_slide; 224 queue_chain_t sr_q; 225 void *sr_root_dir; 226 cpu_type_t sr_cpu_type; 227 cpu_subtype_t sr_cpu_subtype; 228 ipc_port_t sr_mem_entry; 229 mach_vm_offset_t sr_first_mapping; 230 mach_vm_offset_t sr_base_address; 231 mach_vm_size_t sr_size; 232 mach_vm_offset_t sr_pmap_nesting_start; 233 mach_vm_size_t sr_pmap_nesting_size; 234 thread_call_t sr_timer_call; 235 uuid_t sr_uuid; 236 237 #if __ARM_MIXED_PAGE_SIZE__ 238 uint8_t sr_page_shift; 239 #endif /* __ARM_MIXED_PAGE_SIZE__ */ 240 bool sr_mapping_in_progress; /* sr_first_mapping will be != -1 when done */ 241 bool sr_slide_in_progress; 242 bool sr_64bit; 243 bool sr_persists; 244 bool sr_uuid_copied; 245 bool sr_stale; /* This region should never be used again. */ 246 bool sr_driverkit; 247 248 #if __has_feature(ptrauth_calls) 249 bool sr_reslide; /* Special shared region for suspected attacked processes */ 250 uint_t sr_num_auth_section; /* num entries in sr_auth_section */ 251 uint_t sr_next_auth_section; /* used while filling in sr_auth_section */ 252 vm_shared_region_slide_info_t *sr_auth_section; 253 #endif /* __has_feature(ptrauth_calls) */ 254 255 uint32_t sr_rsr_version; 256 257 uint64_t sr_install_time; /* mach_absolute_time() of installation into global list */ 258 uint32_t sr_id; /* identifier for shared cache */ 259 uint32_t sr_images_count; 260 struct dyld_uuid_info_64 *sr_images; 261 }; 262 263 extern kern_return_t vm_shared_region_slide_page( 264 vm_shared_region_slide_info_t si, 265 vm_offset_t vaddr, 266 mach_vm_offset_t uservaddr, 267 uint32_t pageIndex, 268 uint64_t jop_key); 269 extern uint64_t shared_region_find_key(char *shared_region_id); 270 #else /* !MACH_KERNEL_PRIVATE */ 271 272 struct vm_shared_region; 273 struct vm_shared_region_slide_info; 274 struct vm_shared_region_slide_info_entry; 275 struct slide_info_entry_toc; 276 277 #endif /* MACH_KERNEL_PRIVATE */ 278 279 struct _sr_file_mappings { 280 int fd; 281 uint32_t mappings_count; 282 struct shared_file_mapping_slide_np *mappings; 283 uint32_t slide; 284 struct fileproc *fp; 285 struct vnode *vp; 286 memory_object_size_t file_size; 287 memory_object_control_t file_control; 288 }; 289 290 extern void vm_shared_region_init(void); 291 extern kern_return_t vm_shared_region_enter( 292 struct _vm_map *map, 293 struct task *task, 294 boolean_t is_64bit, 295 void *fsroot, 296 cpu_type_t cpu, 297 cpu_subtype_t cpu_subtype, 298 boolean_t reslide, 299 boolean_t is_driverkit, 300 uint32_t rsr_version); 301 extern void vm_shared_region_remove( 302 struct task *task, 303 struct vm_shared_region *sr); 304 extern vm_shared_region_t vm_shared_region_get( 305 struct task *task); 306 extern vm_shared_region_t vm_shared_region_trim_and_get( 307 struct task *task); 308 extern void vm_shared_region_deallocate( 309 struct vm_shared_region *shared_region); 310 extern vm_map_t vm_shared_region_vm_map( 311 struct vm_shared_region *shared_region); 312 extern void vm_shared_region_set( 313 struct task *task, 314 struct vm_shared_region *new_shared_region); 315 extern vm_shared_region_t vm_shared_region_lookup( 316 void *root_dir, 317 cpu_type_t cpu, 318 cpu_subtype_t cpu_subtype, 319 boolean_t is_64bit, 320 int target_page_shift, 321 boolean_t reslide, 322 boolean_t is_driverkit, 323 uint32_t rsr_version); 324 extern kern_return_t vm_shared_region_start_address( 325 struct vm_shared_region *shared_region, 326 mach_vm_offset_t *start_address, 327 task_t task); 328 extern void vm_shared_region_undo_mappings( 329 vm_map_t sr_map, 330 mach_vm_offset_t sr_base_address, 331 struct _sr_file_mappings *srf_mappings, 332 struct _sr_file_mappings *srf_mappings_count, 333 unsigned int mappings_count); 334 __attribute__((noinline)) 335 extern kern_return_t vm_shared_region_map_file( 336 struct vm_shared_region *shared_region, 337 int sr_mappings_count, 338 struct _sr_file_mappings *sr_mappings); 339 extern void *vm_shared_region_root_dir( 340 struct vm_shared_region *shared_region); 341 extern kern_return_t vm_shared_region_sliding_valid(uint32_t slide); 342 extern void vm_commpage_init(void); 343 extern void vm_commpage_text_init(void); 344 extern kern_return_t vm_commpage_enter( 345 struct _vm_map *map, 346 struct task *task, 347 boolean_t is64bit); 348 extern kern_return_t vm_commpage_remove( 349 struct _vm_map *map, 350 struct task *task); 351 int vm_shared_region_slide(uint32_t, 352 mach_vm_offset_t, 353 mach_vm_size_t, 354 mach_vm_offset_t, 355 mach_vm_size_t, 356 mach_vm_offset_t, 357 memory_object_control_t, 358 vm_prot_t); 359 extern void vm_shared_region_pivot(void); 360 extern void vm_shared_region_reslide_stale(boolean_t driverkit); 361 #if __has_feature(ptrauth_calls) 362 __attribute__((noinline)) 363 extern kern_return_t vm_shared_region_auth_remap(vm_shared_region_t sr); 364 #endif /* __has_feature(ptrauth_calls) */ 365 extern void vm_shared_region_reference(vm_shared_region_t sr); 366 367 #endif /* KERNEL_PRIVATE */ 368 369 #endif /* _VM_SHARED_REGION_H_ */ 370