In the unlikely event that a 32bit vcpu traps into the hypervisor on an instruction that is located right at the end of the 32bit range, the emulation of that instruction is going to increment PC past the 32bit range. This isn't great, as userspace can then observe this value and get a bit confused.
Conversly, userspace can do things like (in the context of a 64bit guest that is capable of 32bit EL0) setting PSTATE to AArch64-EL0, set PC to a 64bit value, change PSTATE to AArch32-USR, and observe that PC hasn't been truncated. More confusion.
Fix both by: - truncating PC increments for 32bit guests - sanitizing all 32bit regs every time a core reg is changed by userspace, and that PSTATE indicates a 32bit mode.
Cc: stable@vger.kernel.org Acked-by: Will Deacon will@kernel.org Signed-off-by: Marc Zyngier maz@kernel.org --- arch/arm64/kvm/guest.c | 7 +++++++ virt/kvm/arm/hyp/aarch32.c | 8 ++++++-- 2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 23ebe51410f0..50a279d3ddd7 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -200,6 +200,13 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) }
memcpy((u32 *)regs + off, valp, KVM_REG_SIZE(reg->id)); + + if (*vcpu_cpsr(vcpu) & PSR_MODE32_BIT) { + int i; + + for (i = 0; i < 16; i++) + *vcpu_reg32(vcpu, i) = (u32)*vcpu_reg32(vcpu, i); + } out: return err; } diff --git a/virt/kvm/arm/hyp/aarch32.c b/virt/kvm/arm/hyp/aarch32.c index d31f267961e7..25c0e47d57cb 100644 --- a/virt/kvm/arm/hyp/aarch32.c +++ b/virt/kvm/arm/hyp/aarch32.c @@ -125,12 +125,16 @@ static void __hyp_text kvm_adjust_itstate(struct kvm_vcpu *vcpu) */ void __hyp_text kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr) { + u32 pc = *vcpu_pc(vcpu); bool is_thumb;
is_thumb = !!(*vcpu_cpsr(vcpu) & PSR_AA32_T_BIT); if (is_thumb && !is_wide_instr) - *vcpu_pc(vcpu) += 2; + pc += 2; else - *vcpu_pc(vcpu) += 4; + pc += 4; + + *vcpu_pc(vcpu) = pc; + kvm_adjust_itstate(vcpu); }
Hi
[This is an automated email]
This commit has been processed because it contains a -stable tag. The stable tag indicates that it's relevant for the following trees: all
The bot has tested the following trees: v5.6.8, v5.4.36, v4.19.119, v4.14.177, v4.9.220, v4.4.220.
v5.6.8: Build OK! v5.4.36: Build OK! v4.19.119: Build OK! v4.14.177: Failed to apply! Possible dependencies: 00536ec47660 ("KVM: arm/arm64: Prepare to handle deferred save/restore of SPSR_EL1") 256c0960b7b6 ("kvm/arm: use PSR_AA32 definitions") 52f6c4f02164 ("KVM: arm64: Change 32-bit handling of VM system registers") 54ceb1bcf8d8 ("KVM: arm64: Move debug dirty flag calculation out of world switch") 623e1528d409 ("KVM: arm/arm64: Move cc/it checks under hyp's Makefile to avoid instrumentation") 74a64a981662 ("KVM: arm/arm64: Unify 32bit fault injection") 8d404c4c2461 ("KVM: arm64: Rewrite system register accessors to read/write functions") a892819560c4 ("KVM: arm64: Prepare to handle deferred save/restore of 32-bit registers") b220244d4179 ("arm64: vgic-v2: Fix proxying of cpuif access")
v4.9.220: Failed to apply! Possible dependencies: 021234ef3752 ("KVM: arm64: Make kvm_condition_valid32() accessible from EL2") 256c0960b7b6 ("kvm/arm: use PSR_AA32 definitions") 3dbbdf78636e ("KVM: arm/arm64: Report PMU overflow interrupts to userspace irqchip") 52f6c4f02164 ("KVM: arm64: Change 32-bit handling of VM system registers") 54ceb1bcf8d8 ("KVM: arm64: Move debug dirty flag calculation out of world switch") 623e1528d409 ("KVM: arm/arm64: Move cc/it checks under hyp's Makefile to avoid instrumentation") 6c0070366dea ("arm64: KVM: PMU: Refactor pmu_*_el0_disabled") 74a64a981662 ("KVM: arm/arm64: Unify 32bit fault injection") 8d404c4c2461 ("KVM: arm64: Rewrite system register accessors to read/write functions") 9171fa2e0951 ("KVM: arm/arm64: Decouple kvm timer functions from virtual timer") a5a1d1c2914b ("clocksource: Use a plain u64 instead of cycle_t") b7484931e4a8 ("KVM: arm/arm64: PMU: remove request-less vcpu kick") d9e139778376 ("KVM: arm/arm64: Support arch timers with a userspace gic") d9f89b4e9290 ("KVM: arm/arm64: PMU: Fix overflow interrupt injection") f85279b4bd48 ("arm64: KVM: Save/restore the host SPE state when entering/leaving a VM")
v4.4.220: Failed to apply! Possible dependencies: 08dcbfda0774 ("ARM: KVM: Add a HYP-specific header file") 1d58d2cbf723 ("ARM: KVM: Add TLB invalidation code") 33280b4cd1dc ("ARM: KVM: Add banked registers save/restore") 3c29568768df ("ARM: KVM: Add system register accessor macros") 59cbcdb5d83b ("ARM: KVM: Add VFP save/restore") 623e1528d409 ("KVM: arm/arm64: Move cc/it checks under hyp's Makefile to avoid instrumentation") 68130cb5db09 ("ARM: KVM: Use common version of timer-sr.c") b5fa5d3e628b ("ARM: KVM: Use common version of vgic-v2-sr.c") c0c2cdbffef2 ("ARM: KVM: Add vgic v2 save/restore") c7ce6c63a05f ("ARM: KVM: Add CP15 save/restore code") e59bff9bf302 ("ARM: KVM: Add timer save/restore") f1c9cad7c508 ("ARM: KVM: Move kvm/hyp/hyp.h to include/asm/kvm_hyp.h")
NOTE: The patch will not be queued to stable trees until it is upstream.
How should we proceed with this patch?
linux-stable-mirror@lists.linaro.org