aarch64: avoid saving CPACR to a disabled VCPU

seL4_VCPUReg_CPACR was sometimes saved to an inactive current VCPU,
overwriting the previous value and erroneously enabling FPU access.

Signed-off-by: Ryan Barry <ryan.barry@proofcraft.systems>
This commit is contained in:
Ryan Barry
2025-03-12 15:46:52 +11:00
committed by Gerwin Klein
parent 119a189c39
commit 8e18a0b558
3 changed files with 17 additions and 5 deletions

View File

@@ -53,6 +53,16 @@ description indicates whether it is SOURCE-COMPATIBLE, BINARY-COMPATIBLE, or BRE
This was found by Alison Felizzi and independently by Ryan Barry during the integrity proofs for AArch64 hyp mode.
* Fixed: under some circumstances, `seL4_VCPUReg_CPACR` is saved twice to the current VCPU. The value of this
register may change between saves, causing the latter save to unintentionally grant EL0/1 access to the FPU.
1. A thread with an active current VCPU switches to a thread without a VCPU. The current VCPU is disabled.
1.1. `seL4_VCPUReg_CPACR` is saved to the current VCPU.
1.2. `enableFpuEL01` updates the register, enabling FPU access in EL0 and EL1.
2. The thread without a VCPU switches to a thread with a different VCPU to the first
2.1. All registers from `seL4_VCPUReg_TTBR0` to `seL4_VCPUReg_SPSR_EL1` are saved. This range includes
`seL4_VCPUReg_CPACR`, which overwrites the previously saved value and grants FPU access at EL0 and EL1.
### Upgrade Notes
---

View File

@@ -630,8 +630,12 @@ static inline void armv_vcpu_boot_init(void)
#endif
}
static inline void armv_vcpu_save(vcpu_t *vcpu, UNUSED bool_t active)
static inline void armv_vcpu_save(vcpu_t *vcpu, bool_t active)
{
/* If we aren't active then this state already got stored when we were disabled */
if (active) {
vcpu_save_reg(vcpu, seL4_VCPUReg_CPACR);
}
vcpu_save_reg_range(vcpu, seL4_VCPUReg_TTBR0, seL4_VCPUReg_SPSR_EL1);
#ifdef ARM_HYP_CP14_SAVE_AND_RESTORE_VCPU_THREADS

View File

@@ -72,18 +72,16 @@ typedef enum {
} seL4_VCPUFault_Msg;
typedef enum {
/* VM control registers EL1 */
/* System control registers EL1 */
seL4_VCPUReg_SCTLR = 0,
seL4_VCPUReg_CPACR,
seL4_VCPUReg_TTBR0,
seL4_VCPUReg_TTBR1,
seL4_VCPUReg_TCR,
seL4_VCPUReg_MAIR,
seL4_VCPUReg_AMAIR,
seL4_VCPUReg_CIDR,
/* other system registers EL1 */
seL4_VCPUReg_ACTLR,
seL4_VCPUReg_CPACR,
/* exception handling registers EL1 */
seL4_VCPUReg_AFSR0,