Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | /* * Copyright (c) 2019 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef _ARM64_PAC_ASM_H_ #define _ARM64_PAC_ASM_H_ #ifndef __ASSEMBLER__ #error "This header should only be used in .s files" #endif #include <pexpert/arm64/board_config.h> #include <arm64/proc_reg.h> #if HAS_PARAVIRTUALIZED_PAC #include <arm64/hv_hvc.h> #include "smccc_asm.h" #endif #include "assym.s" #if defined(HAS_APPLE_PAC) /* BEGIN IGNORE CODESTYLE */ /** * REPROGRAM_JOP_KEYS * * Loads a userspace process's JOP key (task->jop_pid) into the CPU, and * updates current_cpu_datap()->jop_key accordingly. This reprogramming process * is skipped whenever the "new" JOP key has already been loaded into the CPU. * * skip_label - branch to this label if new_jop_key is already loaded into CPU * new_jop_key - process's jop_pid * cpudatap - current cpu_data_t * * tmp - scratch register */ .macro REPROGRAM_JOP_KEYS skip_label, new_jop_key, cpudatap, tmp ldr \tmp, [\cpudatap, CPU_JOP_KEY] cmp \new_jop_key, \tmp b.eq \skip_label SET_JOP_KEY_REGISTERS \new_jop_key, \tmp str \new_jop_key, [\cpudatap, CPU_JOP_KEY] .endmacro /** * REPROGRAM_ROP_KEYS * * Loads a userspace process's ROP key (task->rop_pid) into the CPU, and * updates current_cpu_datap()->rop_key accordingly. This reprogramming process * is skipped whenever the "new" ROP key has already been loaded into the CPU. * * skip_label - branch to this label if new_rop_key is already loaded into CPU * new_rop_key - process's rop_pid * cpudatap - current cpu_data_t * * tmp - scratch register */ .macro REPROGRAM_ROP_KEYS skip_label, new_rop_key, cpudatap, tmp ldr \tmp, [\cpudatap, CPU_ROP_KEY] cmp \new_rop_key, \tmp b.eq \skip_label SET_ROP_KEY_REGISTERS \new_rop_key, \tmp str \new_rop_key, [\cpudatap, CPU_ROP_KEY] .endmacro /** * SET_JOP_KEY_REGISTERS * * Unconditionally loads a userspace process's JOP key (task->jop_pid) into the * CPU. The caller is responsible for updating current_cpu_datap()->jop_key as * needed. * * new_jop_key - process's jop_pid * tmp - scratch register */ .macro SET_JOP_KEY_REGISTERS new_jop_key, tmp #if HAS_PARAVIRTUALIZED_PAC SAVE_SMCCC_CLOBBERED_REGISTERS /* * We're deliberately calling PAC_SET_EL0_DIVERSIFIER here, even though the * EL0 diversifier affects both A (JOP) and B (ROP) keys. We don't want * SET_JOP_KEY_REGISTERS to have an impact on the EL1 A key state, since * these are the keys the kernel uses to sign pointers on the heap. * * Using new_jop_key as the EL0 diversifer has the same net effect of giving * userspace its own set of JOP keys, but doesn't affect EL1 A key state. */ MOV64 x0, VMAPPLE_PAC_SET_EL0_DIVERSIFIER mov x1, \new_jop_key hvc #0 cbnz x0, . LOAD_SMCCC_CLOBBERED_REGISTERS #endif /* HAS_PARAVIRTUALIZED_PAC */ .endmacro /** * SET_ROP_KEY_REGISTERS * * Unconditionally loads a userspace process's ROP key (task->rop_pid) into the * CPU. The caller is responsible for updating current_cpu_datap()->rop_key as * needed. * * new_rop_key - process's rop_pid * tmp - scratch register */ .macro SET_ROP_KEY_REGISTERS new_rop_key, tmp #if HAS_PARAVIRTUALIZED_PAC SAVE_SMCCC_CLOBBERED_REGISTERS MOV64 x0, VMAPPLE_PAC_SET_B_KEYS mov x1, \new_rop_key hvc #0 cbnz x0, . LOAD_SMCCC_CLOBBERED_REGISTERS #endif /* HAS_PARAVIRTUALIZED_PAC */ .endmacro /** * PAC_INIT_KEY_STATE * * Sets the initial PAC key state, but does not enable the keys. * * tmp - scratch register * tmp2 - scratch register */ .macro PAC_INIT_KEY_STATE tmp, tmp2 #if HAS_PARAVIRTUALIZED_PAC #if HIBERNATION #error PAC_INIT_KEY_STATE is not implemented for HAS_PARAVIRTUALIZED_PAC && HIBERNATION #endif /* * This call clobbers x0-x3. However we only initialize PAC at a point in * common_start where x0-x3 are safe to clobber, and where we don't yet have * a working stack to stash the existing values anyway. */ mov x0, #VMAPPLE_PAC_SET_INITIAL_STATE hvc #0 cbnz x0, . #endif /* HAS_PARAVIRTUALIZED_PAC */ .endmacro /* * For pacga diversification we always put the tag type in the * lowest 4 bits of the first source to pacga. * * We diversify by use case, to prevent attackers from using * pacga results from one usecase to attack another usecase. * * First pacga when using a context: * pacga chain_reg, (context << 4) + PACGA_TAG_xxx, first_data * * First pacga without context: * pacga chain_reg, PACGA_TAG_xxx, first_data * * Subsequent pacga's: * pacga chain_reg, chain_reg + PACGA_TAG_xxx, next_data * * chain_reg layout * 63 .. 32 || 31 .. 4 | 3 .. 0 * chain value || available per use case | TAG */ #define PACGA_TAG_0 0b0000 #define PACGA_TAG_BLOB 0b0001 #define PACGA_TAG_THREAD 0b0010 #define PACGA_TAG_IRG 0b0011 #define PACGA_TAG_HV 0b0100 #define PACGA_TAG_ADDRPERM 0b0101 #define PACGA_TAG_6 0b0110 #define PACGA_TAG_7 0b0111 #define PACGA_TAG_8 0b1000 #define PACGA_TAG_9 0b1001 /* * This one is never actually used, it is here to effectively made the THREAD TAG * 3 bits, so we can sign enough of PC there for the foreseeable future (up to 128M of kernel .text) */ #define PACGA_TAG_THREAD_2 0b1010 #define PACGA_TAG_b 0b1011 #define PACGA_TAG_c 0b1100 #define PACGA_TAG_d 0b1101 #define PACGA_TAG_e 0b1110 #define PACGA_TAG_f 0b1111 #if NEEDS_MTE_IRG_RESEED /* * This generates a new 48 bit seed, based on the reseed_counter. * We use the PACGA_TAG_IRG here. and we generate two 32bit values * using pacga twice. using: * cpu_number || 0b0000 || TAG_IRG(0b0011), counter * cpu_number || 0b0001 || TAG_IRG(0b0011), counter * * Needs three registers to use, all will be clobbered * Expects interrupts to be disabled. */ .macro PACGA_IRG_RESEED x, y, z mrs \x, TPIDR_EL1 ldr \x, [\x, ACT_CPUDATAP] // No need for atomic - These are per CPU and interrupts are disabled ldr \z, [\x, CPU_IRG_RESEED_COUNTER] add \y, \z, #1 str \y, [\x, CPU_IRG_RESEED_COUNTER] ldrsh \y, [\x, CPU_NUMBER_GS] lsl \y, \y, 8 add \y, \y, #0x3 // Will be resolved after rdar://123719761 pacga \x, \y, \z // PACGA_TAG_IRG add \y, \y, 0x10 pacga \y, \y, \z // PACGA_TAG_IRG eor \y, \x, \y, LSR #32 #if APPLEVIRTUALPLATFORM mrs \x, GCR_EL1 tbz \x, GCR_EL1_RRND_OFFSET, Lpacga_irg_reseed_arm_mode_\@ #endif orr \y, \y, (0b111 << RGSR_EL1_SEED_OFFSET) #if APPLEVIRTUALPLATFORM Lpacga_irg_reseed_arm_mode_\@: #endif msr RGSR_EL1, \y .endmacro #endif /* NEEDS_MTE_IRG_RESEED */ /* END IGNORE CODESTYLE */ #endif /* defined(HAS_APPLE_PAC) */ #endif /* _ARM64_PAC_ASM_H_ */ /* vim: set ts=4 ft=asm: */ |