KVM: s390: keyop: use mmu_lock to read gmap->asce

Every other dat_* consumer in this file (kvm_s390_get_skeys,
set_skeys, get_cmma_bits, set_cmma_bits, MEM_CLR_CMMA,
kvm_s390_fixup_prefix, kvm_test_age_gfn, kvm_age_gfn) reads
kvm->arch.gmap->asce *inside* the mmu_lock read-side. keyop is the only
outlier.

gmap->asce is mutated under write_lock(mmu_lock) by gmap_set_limit()
and keyop might use a stale asce value for walking as KVM_S390_KEYOP
and KVM_S390_VM_MEM_LIMIT_SIZE can run concurrently. This can result
in memory corruption.

Fixes: 0ee4ddc164 ("KVM: s390: Storage key manipulation IOCTL")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Message-ID: <20260811153738.206885-2-borntraeger@linux.ibm.com>
This commit is contained in:
Christian Borntraeger 2026-08-11 17:37:35 +02:00 committed by Claudio Imbrenda
parent 546dde823a
commit da07a751ef

View File

@ -562,11 +562,12 @@ static void __kvm_s390_exit(void)
static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op,
unsigned long addr, union skey skey)
{
union asce asce = kvm->arch.gmap->asce;
gfn_t gfn = gpa_to_gfn(addr);
union asce asce;
int r;
guard(read_lock)(&kvm->mmu_lock);
asce = kvm->arch.gmap->asce;
switch (op) {
case KVM_S390_KEYOP_SSKE: