KVM: s390: Fix unlikely NULL gmap dereference

When creating a new vCPU, kvm_vm_ioctl_create_vcpu() will call
kvm_arch_vcpu_postcreate() after the file descriptor for the new vCPU
has been created. The new file descriptor has not been returned yet,
but a malicious userspace program could try to guess it.

If a malicious userspace program manages to start the newly created vCPU
before kvm_arch_vcpu_postcreate() is called, __vcpu_run() will try to
dereference vcpu->arch.gmap and trigger a NULL pointer dereference.

Fix this by adding a new field to struct kvm_vcpu_arch to keep track of
the initialization status of the vCPU. Refuse to run a vCPU that is not
fully initialized.

Fixes: dafd032a15 ("KVM: s390: move vcpu specific initalization to a later point")
Fixes: e38c884df9 ("KVM: s390: Switch to new gmap")
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Message-ID: <20260803124040.126471-2-imbrenda@linux.ibm.com>
This commit is contained in:
Claudio Imbrenda 2026-08-03 14:40:28 +02:00
parent 16b0798024
commit 496e0f706b
2 changed files with 12 additions and 0 deletions

View File

@ -440,6 +440,7 @@ struct kvm_vcpu_arch {
bool skey_enabled;
/* Indicator if the access registers have been loaded from guest */
bool acrs_loaded;
bool initialized;
struct kvm_s390_pv_vcpu pv;
union diag318_info diag318_info;
struct kvm_s390_mmu_cache *mc;

View File

@ -3613,6 +3613,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
vcpu->kvm->arch.user_operexec)
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
/* Pairs with smp_load_acquire() in kvm_arch_vcpu_ioctl_run() and kvm_arch_vcpu_ioctl() */
smp_store_release(&vcpu->arch.initialized, true);
}
static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
@ -5039,6 +5042,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
kvm_run->kvm_dirty_regs & ~KVM_SYNC_S390_VALID_FIELDS)
return -EINVAL;
/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
if (!smp_load_acquire(&vcpu->arch.initialized))
return -EINVAL;
vcpu_load(vcpu);
if (guestdbg_exit_pending(vcpu)) {
@ -5523,6 +5530,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
long r;
u16 rc, rrc;
/* Pairs with smp_store_release() in kvm_arch_vcpu_postcreate() */
if (!smp_load_acquire(&vcpu->arch.initialized))
return -EINVAL;
vcpu_load(vcpu);
switch (ioctl) {