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