~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm64/kvm/pauth.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/arm64/kvm/pauth.c (Version linux-6.12-rc7) and /arch/i386/kvm/pauth.c (Version linux-5.1.21)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  * Copyright (C) 2024 - Google LLC                
  4  * Author: Marc Zyngier <maz@kernel.org>          
  5  *                                                
  6  * Primitive PAuth emulation for ERETAA/ERETAB    
  7  *                                                
  8  * This code assumes that is is run from EL2,     
  9  * the emulation of ERETAx for a guest hypervi    
 10  * baked-in assumptions and shortcuts.            
 11  *                                                
 12  * Do no reuse for anything else!                 
 13  */                                               
 14                                                   
 15 #include <linux/kvm_host.h>                       
 16                                                   
 17 #include <asm/gpr-num.h>                          
 18 #include <asm/kvm_emulate.h>                      
 19 #include <asm/pointer_auth.h>                     
 20                                                   
 21 /* PACGA Xd, Xn, Xm */                            
 22 #define PACGA(d,n,m)                              
 23         asm volatile(__DEFINE_ASM_GPR_NUMS        
 24                      ".inst 0x9AC03000            
 25                      "(.L__gpr_num_%[Rd] << 0)    
 26                      "(.L__gpr_num_%[Rn] << 5)    
 27                      "(.L__gpr_num_%[Rm] << 16    
 28                      : [Rd] "=r" ((d))            
 29                      : [Rn] "r" ((n)), [Rm] "r    
 30                                                   
 31 static u64 compute_pac(struct kvm_vcpu *vcpu,     
 32                        struct ptrauth_key ikey    
 33 {                                                 
 34         struct ptrauth_key gkey;                  
 35         u64 mod, pac = 0;                         
 36                                                   
 37         preempt_disable();                        
 38                                                   
 39         if (!vcpu_get_flag(vcpu, SYSREGS_ON_CP    
 40                 mod = __vcpu_sys_reg(vcpu, SP_    
 41         else                                      
 42                 mod = read_sysreg(sp_el1);        
 43                                                   
 44         gkey.lo = read_sysreg_s(SYS_APGAKEYLO_    
 45         gkey.hi = read_sysreg_s(SYS_APGAKEYHI_    
 46                                                   
 47         __ptrauth_key_install_nosync(APGA, ike    
 48         isb();                                    
 49                                                   
 50         PACGA(pac, ptr, mod);                     
 51         isb();                                    
 52                                                   
 53         __ptrauth_key_install_nosync(APGA, gke    
 54                                                   
 55         preempt_enable();                         
 56                                                   
 57         /* PAC in the top 32bits */               
 58         return pac;                               
 59 }                                                 
 60                                                   
 61 static bool effective_tbi(struct kvm_vcpu *vcp    
 62 {                                                 
 63         u64 tcr = vcpu_read_sys_reg(vcpu, TCR_    
 64         bool tbi, tbid;                           
 65                                                   
 66         /*                                        
 67          * Since we are authenticating an inst    
 68          * to take TBID into account. If E2H==    
 69          * TCR_EL2 only has a single TBI/TBID.    
 70          * this case, this is likely a guest b    
 71          */                                       
 72         if (!vcpu_el2_e2h_is_set(vcpu)) {         
 73                 tbi = tcr & BIT(20);              
 74                 tbid = tcr & BIT(29);             
 75         } else if (bit55) {                       
 76                 tbi = tcr & TCR_TBI1;             
 77                 tbid = tcr & TCR_TBID1;           
 78         } else {                                  
 79                 tbi = tcr & TCR_TBI0;             
 80                 tbid = tcr & TCR_TBID0;           
 81         }                                         
 82                                                   
 83         return tbi && !tbid;                      
 84 }                                                 
 85                                                   
 86 static int compute_bottom_pac(struct kvm_vcpu     
 87 {                                                 
 88         static const int maxtxsz = 39; // Revi    
 89         static const int mintxsz = 16; // (if)    
 90         u64 tcr = vcpu_read_sys_reg(vcpu, TCR_    
 91         int txsz;                                 
 92                                                   
 93         if (!vcpu_el2_e2h_is_set(vcpu) || !bit    
 94                 txsz = FIELD_GET(TCR_T0SZ_MASK    
 95         else                                      
 96                 txsz = FIELD_GET(TCR_T1SZ_MASK    
 97                                                   
 98         return 64 - clamp(txsz, mintxsz, maxtx    
 99 }                                                 
100                                                   
101 static u64 compute_pac_mask(struct kvm_vcpu *v    
102 {                                                 
103         int bottom_pac;                           
104         u64 mask;                                 
105                                                   
106         bottom_pac = compute_bottom_pac(vcpu,     
107                                                   
108         mask = GENMASK(54, bottom_pac);           
109         if (!effective_tbi(vcpu, bit55))          
110                 mask |= GENMASK(63, 56);          
111                                                   
112         return mask;                              
113 }                                                 
114                                                   
115 static u64 to_canonical_addr(struct kvm_vcpu *    
116 {                                                 
117         bool bit55 = !!(ptr & BIT(55));           
118                                                   
119         if (bit55)                                
120                 return ptr | mask;                
121                                                   
122         return ptr & ~mask;                       
123 }                                                 
124                                                   
125 static u64 corrupt_addr(struct kvm_vcpu *vcpu,    
126 {                                                 
127         bool bit55 = !!(ptr & BIT(55));           
128         u64 mask, error_code;                     
129         int shift;                                
130                                                   
131         if (effective_tbi(vcpu, bit55)) {         
132                 mask = GENMASK(54, 53);           
133                 shift = 53;                       
134         } else {                                  
135                 mask = GENMASK(62, 61);           
136                 shift = 61;                       
137         }                                         
138                                                   
139         if (esr_iss_is_eretab(kvm_vcpu_get_esr    
140                 error_code = 2 << shift;          
141         else                                      
142                 error_code = 1 << shift;          
143                                                   
144         ptr &= ~mask;                             
145         ptr |= error_code;                        
146                                                   
147         return ptr;                               
148 }                                                 
149                                                   
150 /*                                                
151  * Authenticate an ERETAA/ERETAB instruction,     
152  * authentication succeeded and false otherwis    
153  * contains the VA to ERET to. Potential excep    
154  * to the caller.                                 
155  */                                               
156 bool kvm_auth_eretax(struct kvm_vcpu *vcpu, u6    
157 {                                                 
158         u64 sctlr = vcpu_read_sys_reg(vcpu, SC    
159         u64 esr = kvm_vcpu_get_esr(vcpu);         
160         u64 ptr, cptr, pac, mask;                 
161         struct ptrauth_key ikey;                  
162                                                   
163         *elr = ptr = vcpu_read_sys_reg(vcpu, E    
164                                                   
165         /* We assume we're already in the cont    
166         if (esr_iss_is_eretab(esr)) {             
167                 if (!(sctlr & SCTLR_EL1_EnIB))    
168                         return true;              
169                                                   
170                 ikey.lo = __vcpu_sys_reg(vcpu,    
171                 ikey.hi = __vcpu_sys_reg(vcpu,    
172         } else {                                  
173                 if (!(sctlr & SCTLR_EL1_EnIA))    
174                         return true;              
175                                                   
176                 ikey.lo = __vcpu_sys_reg(vcpu,    
177                 ikey.hi = __vcpu_sys_reg(vcpu,    
178         }                                         
179                                                   
180         mask = compute_pac_mask(vcpu, !!(ptr &    
181         cptr = to_canonical_addr(vcpu, ptr, ma    
182                                                   
183         pac = compute_pac(vcpu, cptr, ikey);      
184                                                   
185         /*                                        
186          * Slightly deviate from the pseudocod    
187          * match with the signed pointer, then    
188          * Anything after this point is pure e    
189          */                                       
190         if ((pac & mask) == (ptr & mask)) {       
191                 *elr = cptr;                      
192                 return true;                      
193         }                                         
194                                                   
195         /*                                        
196          * Authentication failed, corrupt the     
197          * PAuth2 isn't implemented, or some X    
198          */                                       
199         if (!kvm_has_pauth(vcpu->kvm, PAuth2))    
200                 cptr = corrupt_addr(vcpu, cptr    
201         else                                      
202                 cptr = ptr ^ (pac & mask);        
203                                                   
204         *elr = cptr;                              
205         return false;                             
206 }                                                 
207                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php