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