| 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 | |
| 64 | extern zone_t ads_zone; |
| 65 | |
| 66 | kern_return_t |
| 67 | machine_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(ds: 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(src: tstate, target: (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(ds: 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(src: tstate, target: (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(ds: 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(src: tstate, target: (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 | |
| 148 | kern_return_t |
| 149 | machine_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(s: state, n: sizeof(*tstate)); |
| 165 | } else { |
| 166 | copy_legacy_debug_state(src: (arm_legacy_debug_state_t*) task->task_debug, target: 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(s: state, n: sizeof(*tstate)); |
| 181 | } else { |
| 182 | copy_debug_state32(src: (arm_debug_state32_t*) task->task_debug, target: 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(s: state, n: sizeof(*tstate)); |
| 197 | } else { |
| 198 | copy_debug_state64(src: (arm_debug_state64_t*) task->task_debug, target: 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 | |
| 211 | void |
| 212 | machine_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 | |
| 225 | kern_return_t |
| 226 | machine_thread_inherit_taskwide( |
| 227 | thread_t thread, |
| 228 | task_t parent_task) |
| 229 | { |
| 230 | if (parent_task->task_debug) { |
| 231 | int flavor; |
| 232 | mach_msg_type_number_t count; |
| 233 | |
| 234 | flavor = task_has_64Bit_data(parent_task) ? ARM_DEBUG_STATE64 : ARM_DEBUG_STATE32; |
| 235 | count = task_has_64Bit_data(parent_task) ? ARM_DEBUG_STATE64_COUNT : ARM_DEBUG_STATE32_COUNT; |
| 236 | |
| 237 | return machine_thread_set_state(thread, flavor, state: parent_task->task_debug, count); |
| 238 | } |
| 239 | |
| 240 | return KERN_SUCCESS; |
| 241 | } |
| 242 | |
| 243 | |
| 244 | void |
| 245 | machine_task_init(__unused task_t new_task, |
| 246 | __unused task_t parent_task, |
| 247 | __unused boolean_t memory_inherit) |
| 248 | { |
| 249 | } |
| 250 | |
| 251 | /* |
| 252 | * machine_task_process_signature |
| 253 | * |
| 254 | * Called to allow code signature dependent adjustments to the task |
| 255 | * state. It is not safe to assume that this function is only called |
| 256 | * once per task, as a signature may be attached later. |
| 257 | * |
| 258 | * On error, this function should point error_msg to a static error |
| 259 | * string (the caller will not free it). |
| 260 | */ |
| 261 | kern_return_t |
| 262 | machine_task_process_signature( |
| 263 | task_t task, |
| 264 | uint32_t const __unused platform, |
| 265 | uint32_t const __unused sdk, |
| 266 | char const ** __unused error_msg) |
| 267 | { |
| 268 | assert(error_msg != NULL); |
| 269 | |
| 270 | kern_return_t kr = KERN_SUCCESS; |
| 271 | |
| 272 | bool const x18_entitled = |
| 273 | IOTaskHasEntitlement(task, entitlement: "com.apple.private.custom-x18-abi" ) || |
| 274 | IOTaskHasEntitlement(task, entitlement: "com.apple.private.uexc" ); |
| 275 | |
| 276 | #if !__ARM_KERNEL_PROTECT__ |
| 277 | task->preserve_x18 = x18_entitled; |
| 278 | |
| 279 | /* |
| 280 | * Temporary override for tasks before macOS 13. |
| 281 | * Those were allowed to use x18 for their purposes on Apple Silicon. |
| 282 | */ |
| 283 | |
| 284 | if (platform == PLATFORM_MACOS && sdk < 0xd0000) { |
| 285 | task->preserve_x18 = true; |
| 286 | } |
| 287 | #else /* !__ARM_KERNEL_PROTECT__ */ |
| 288 | if (x18_entitled) { |
| 289 | /* |
| 290 | * This *will* make you sad, because it means you are |
| 291 | * trying to use x18 on a device where that's just not |
| 292 | * possible. As these are private entitlements, we can |
| 293 | * prevent confusing damage now. |
| 294 | */ |
| 295 | |
| 296 | *error_msg = "process has entitlement that indicates custom x18 ABI usage, not available on this device" ; |
| 297 | kr = KERN_FAILURE; |
| 298 | } |
| 299 | #endif /* !__ARM_KERNEL_PROTECT__ */ |
| 300 | |
| 301 | return kr; |
| 302 | } |
| 303 | |