diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2018-09-27 16:53:22 +0100 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2018-10-01 14:38:26 +0100 |
commit | 2a3f93459d689d990b3ecfbe782fec89b97d3279 (patch) | |
tree | fe727ff9274645032d41c463d5c3593b4760f1dd /arch/arm64/kvm/guest.c | |
parent | d26c25a9d19b5976b319af528886f89cf455692d (diff) | |
download | linux-2a3f93459d689d990b3ecfbe782fec89b97d3279.tar.gz linux-2a3f93459d689d990b3ecfbe782fec89b97d3279.tar.bz2 linux-2a3f93459d689d990b3ecfbe782fec89b97d3279.zip |
arm64: KVM: Sanitize PSTATE.M when being set from userspace
Not all execution modes are valid for a guest, and some of them
depend on what the HW actually supports. Let's verify that what
userspace provides is compatible with both the VM settings and
the HW capabilities.
Cc: <stable@vger.kernel.org>
Fixes: 0d854a60b1d7 ("arm64: KVM: enable initialization of a 32bit vcpu")
Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/kvm/guest.c')
-rw-r--r-- | arch/arm64/kvm/guest.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 3088463bafc1..a6c9fbaeaefc 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -152,17 +152,25 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) } if (off == KVM_REG_ARM_CORE_REG(regs.pstate)) { - u32 mode = (*(u32 *)valp) & PSR_AA32_MODE_MASK; + u64 mode = (*(u64 *)valp) & PSR_AA32_MODE_MASK; switch (mode) { case PSR_AA32_MODE_USR: + if (!system_supports_32bit_el0()) + return -EINVAL; + break; case PSR_AA32_MODE_FIQ: case PSR_AA32_MODE_IRQ: case PSR_AA32_MODE_SVC: case PSR_AA32_MODE_ABT: case PSR_AA32_MODE_UND: + if (!vcpu_el1_is_32bit(vcpu)) + return -EINVAL; + break; case PSR_MODE_EL0t: case PSR_MODE_EL1t: case PSR_MODE_EL1h: + if (vcpu_el1_is_32bit(vcpu)) + return -EINVAL; break; default: err = -EINVAL; |