osfmk/arm64/machine_task.c

xnu source @ f6217f8 2025-10-16 · 365 lines · view on GitHub
1/* 2 * Copyright (c) 2000-2016 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 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * Mach Operating System 33 * Copyright (c) 1991,1990 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56 57#include <kern/task.h> 58#include <kern/thread.h> 59#include <arm/misc_protos.h> 60 61#include <IOKit/IOBSD.h> 62 63 64extern zone_t ads_zone; 65 66kern_return_t 67machine_task_set_state( 68 task_t task, 69 int flavor, 70 thread_state_t state, 71 mach_msg_type_number_t state_count) 72{ 73 switch (flavor) { 74 case ARM_DEBUG_STATE: 75 { 76 arm_legacy_debug_state_t *tstate = (arm_legacy_debug_state_t *) state; 77 if (task_has_64Bit_data(task) || 78 (state_count != ARM_LEGACY_DEBUG_STATE_COUNT) || 79 (!debug_legacy_state_is_valid(tstate))) { 80 return KERN_INVALID_ARGUMENT; 81 } 82 83 if (task->task_debug == NULL) { 84 task->task_debug = zalloc_flags(ads_zone, 85 Z_WAITOK | Z_NOFAIL); 86 } 87 88 copy_legacy_debug_state(tstate, (arm_legacy_debug_state_t *) task->task_debug, FALSE); /* FALSE OR TRUE doesn't matter since we are ignoring it for arm */ 89 90 return KERN_SUCCESS; 91 } 92 case ARM_DEBUG_STATE32: 93 { 94 arm_debug_state32_t *tstate = (arm_debug_state32_t *) state; 95 if (task_has_64Bit_data(task) || 96 (state_count != ARM_DEBUG_STATE32_COUNT) || 97 (!debug_state_is_valid32(tstate))) { 98 return KERN_INVALID_ARGUMENT; 99 } 100 101 if (task->task_debug == NULL) { 102 task->task_debug = zalloc_flags(ads_zone, 103 Z_WAITOK | Z_NOFAIL); 104 } 105 106 copy_debug_state32(tstate, (arm_debug_state32_t *) task->task_debug, FALSE); /* FALSE OR TRUE doesn't matter since we are ignoring it for arm */ 107 108 return KERN_SUCCESS; 109 } 110 case ARM_DEBUG_STATE64: 111 { 112 arm_debug_state64_t *tstate = (arm_debug_state64_t *) state; 113 114 if ((!task_has_64Bit_data(task)) || 115 (state_count != ARM_DEBUG_STATE64_COUNT) || 116 (!debug_state_is_valid64(tstate))) { 117 return KERN_INVALID_ARGUMENT; 118 } 119 120 if (task->task_debug == NULL) { 121 task->task_debug = zalloc_flags(ads_zone, 122 Z_WAITOK | Z_NOFAIL); 123 } 124 125 copy_debug_state64(tstate, (arm_debug_state64_t *) task->task_debug, FALSE); /* FALSE OR TRUE doesn't matter since we are ignoring it for arm */ 126 127 return KERN_SUCCESS; 128 } 129 case THREAD_STATE_NONE: /* Using this flavor to clear task_debug */ 130 { 131 if (task->task_debug != NULL) { 132 zfree(ads_zone, task->task_debug); 133 task->task_debug = NULL; 134 135 return KERN_SUCCESS; 136 } 137 return KERN_FAILURE; 138 } 139 default: 140 { 141 return KERN_INVALID_ARGUMENT; 142 } 143 } 144 145 return KERN_FAILURE; 146} 147 148kern_return_t 149machine_task_get_state(task_t task, 150 int flavor, 151 thread_state_t state, 152 mach_msg_type_number_t *state_count) 153{ 154 switch (flavor) { 155 case ARM_DEBUG_STATE: 156 { 157 arm_legacy_debug_state_t *tstate = (arm_legacy_debug_state_t *) state; 158 159 if (task_has_64Bit_data(task) || (*state_count != ARM_LEGACY_DEBUG_STATE_COUNT)) { 160 return KERN_INVALID_ARGUMENT; 161 } 162 163 if (task->task_debug == NULL) { 164 bzero(state, sizeof(*tstate)); 165 } else { 166 copy_legacy_debug_state((arm_legacy_debug_state_t*) task->task_debug, tstate, FALSE); /* FALSE OR TRUE doesn't matter since we are ignoring it for arm */ 167 } 168 169 return KERN_SUCCESS; 170 } 171 case ARM_DEBUG_STATE32: 172 { 173 arm_debug_state32_t *tstate = (arm_debug_state32_t *) state; 174 175 if (task_has_64Bit_data(task) || (*state_count != ARM_DEBUG_STATE32_COUNT)) { 176 return KERN_INVALID_ARGUMENT; 177 } 178 179 if (task->task_debug == NULL) { 180 bzero(state, sizeof(*tstate)); 181 } else { 182 copy_debug_state32((arm_debug_state32_t*) task->task_debug, tstate, FALSE); /* FALSE OR TRUE doesn't matter since we are ignoring it for arm */ 183 } 184 185 return KERN_SUCCESS; 186 } 187 case ARM_DEBUG_STATE64: 188 { 189 arm_debug_state64_t *tstate = (arm_debug_state64_t *) state; 190 191 if ((!task_has_64Bit_data(task)) || (*state_count != ARM_DEBUG_STATE64_COUNT)) { 192 return KERN_INVALID_ARGUMENT; 193 } 194 195 if (task->task_debug == NULL) { 196 bzero(state, sizeof(*tstate)); 197 } else { 198 copy_debug_state64((arm_debug_state64_t*) task->task_debug, tstate, FALSE); /* FALSE OR TRUE doesn't matter since we are ignoring it for arm */ 199 } 200 201 return KERN_SUCCESS; 202 } 203 default: 204 { 205 return KERN_INVALID_ARGUMENT; 206 } 207 } 208 return KERN_FAILURE; 209} 210 211void 212machine_task_terminate(task_t task) 213{ 214 if (task) { 215 void *task_debug; 216 task_debug = task->task_debug; 217 if (task_debug != NULL) { 218 task->task_debug = NULL; 219 zfree(ads_zone, task_debug); 220 } 221 } 222} 223 224 225kern_return_t 226machine_thread_inherit_taskwide( 227 thread_t thread, 228 task_t parent_task) 229{ 230 kern_return_t kr = KERN_SUCCESS; 231 232 if (parent_task->task_debug) { 233 int flavor; 234 mach_msg_type_number_t count; 235 236 flavor = task_has_64Bit_data(parent_task) ? ARM_DEBUG_STATE64 : ARM_DEBUG_STATE32; 237 count = task_has_64Bit_data(parent_task) ? ARM_DEBUG_STATE64_COUNT : ARM_DEBUG_STATE32_COUNT; 238 239 kr = machine_thread_set_state(thread, flavor, parent_task->task_debug, count); 240 } 241 242 return kr; 243} 244 245 246void 247machine_task_init(__unused task_t new_task, 248 __unused task_t parent_task, 249 __unused boolean_t memory_inherit) 250{ 251} 252 253/** 254 * Converts an OS version maj.min.patch into the format embedded in code 255 * signatures. 256 * 257 * @param maj_version major version number (x) 258 * @param min_version minor version number (y) 259 * @param patch_version patch version number (z) 260 * @return the version number encoded as xxxx.yy.zz 261 */ 262static inline uint32_t 263sdk_version(uint16_t maj_version, uint8_t min_version, uint8_t patch_version) 264{ 265 return (maj_version << 16) | (min_version << 8) | (patch_version << 0); 266} 267 268/** 269 * Determines whether the process was compiled with an SDK targeting an OS from 270 * fall 2024 or later. 271 * 272 * @param platform one of PLATFORM_* 273 * @param sdk the SDK version embedded in the code signature 274 */ 275static bool 276platform_and_sdk_fall_2024_os_or_later(uint32_t platform, uint32_t sdk) 277{ 278 switch (platform) { 279 case PLATFORM_MACOS: 280 return sdk >= sdk_version(15, 0, 0); 281 case PLATFORM_IOS: 282 case PLATFORM_IOSSIMULATOR: 283 case PLATFORM_MACCATALYST: 284 return sdk >= sdk_version(18, 0, 0); 285 case PLATFORM_TVOS: 286 case PLATFORM_TVOSSIMULATOR: 287 return sdk >= sdk_version(18, 0, 0); 288 case PLATFORM_WATCHOS: 289 case PLATFORM_WATCHOSSIMULATOR: 290 return sdk >= sdk_version(11, 0, 0); 291 case PLATFORM_DRIVERKIT: 292 return sdk >= sdk_version(24, 0, 0); 293 default: 294 return true; 295 } 296} 297 298/* 299 * machine_task_process_signature 300 * 301 * Called to allow code signature dependent adjustments to the task 302 * state. It is not safe to assume that this function is only called 303 * once per task, as a signature may be attached later. 304 * 305 * On error, this function should point error_msg to a static error 306 * string (the caller will not free it). 307 */ 308kern_return_t 309machine_task_process_signature( 310 task_t task, 311 uint32_t const __unused platform, 312 uint32_t const __unused sdk, 313 char const ** __unused error_msg) 314{ 315 assert(error_msg != NULL); 316 317 kern_return_t kr = KERN_SUCCESS; 318 319 bool const x18_entitled = 320 IOTaskHasEntitlement(task, "com.apple.private.custom-x18-abi") || 321 IOTaskHasEntitlement(task, "com.apple.private.uexc"); 322 323#if !__ARM_KERNEL_PROTECT__ 324 task->preserve_x18 = x18_entitled; 325 326 /* 327 * Temporary override for tasks before macOS 13. 328 * Those were allowed to use x18 for their purposes on Apple Silicon. 329 */ 330 331 if (platform == PLATFORM_MACOS && sdk < sdk_version(13, 0, 0)) { 332 task->preserve_x18 = true; 333 } 334#else /* !__ARM_KERNEL_PROTECT__ */ 335 if (x18_entitled) { 336 /* 337 * This *will* make you sad, because it means you are 338 * trying to use x18 on a device where that's just not 339 * possible. As these are private entitlements, we can 340 * prevent confusing damage now. 341 */ 342 343 *error_msg = "process has entitlement that indicates custom x18 ABI usage, not available on this device"; 344 kr = KERN_FAILURE; 345 } 346#endif /* !__ARM_KERNEL_PROTECT__ */ 347 348 /* The task defaults to enable ARMv8.7 extensions if the SDK is recent. */ 349 bool uses_1ghz_timebase = platform_and_sdk_fall_2024_os_or_later(platform, sdk); 350 351#if CONFIG_ROSETTA 352 /* Rosetta tasks expect Apple timebase. */ 353 uses_1ghz_timebase = uses_1ghz_timebase && (!task_is_translated(task)); 354#endif /* CONFIG_ROSETTA */ 355 356 task->uses_1ghz_timebase = uses_1ghz_timebase; 357 358 return kr; 359} 360 361bool 362ml_task_uses_1ghz_timebase(const task_t task) 363{ 364 return task->uses_1ghz_timebase; 365}