]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Prevent unsupported memslot operations on protected VMs
authorWill Deacon <will@kernel.org>
Mon, 30 Mar 2026 14:48:10 +0000 (15:48 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 30 Mar 2026 15:58:07 +0000 (16:58 +0100)
Protected VMs do not support deleting or moving memslots after first
run nor do they support read-only or dirty logging.

Return -EPERM to userspace if such an operation is attempted.

Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
Link: https://patch.msgid.link/20260330144841.26181-10-will@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pkvm.c

index 5e7821fe0fc45837707198c59f428c8ec8e92d5d..b3cc5dfe572378ddb2b96458a6f147e3a8de159a 100644 (file)
@@ -2414,6 +2414,19 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
        hva_t hva, reg_end;
        int ret = 0;
 
+       if (kvm_vm_is_protected(kvm)) {
+               /* Cannot modify memslots once a pVM has run. */
+               if (pkvm_hyp_vm_is_created(kvm) &&
+                   (change == KVM_MR_DELETE || change == KVM_MR_MOVE)) {
+                       return -EPERM;
+               }
+
+               if (new &&
+                   new->flags & (KVM_MEM_LOG_DIRTY_PAGES | KVM_MEM_READONLY)) {
+                       return -EPERM;
+               }
+       }
+
        if (change != KVM_MR_CREATE && change != KVM_MR_MOVE &&
                        change != KVM_MR_FLAGS_ONLY)
                return 0;
index dd93dfdfe52d416a03387748f2dad7ec9595780e..94b70eb80aa818223ab2eb27ddfbdafb87c6bffb 100644 (file)
@@ -192,10 +192,16 @@ int pkvm_create_hyp_vm(struct kvm *kvm)
 {
        int ret = 0;
 
+       /*
+        * Synchronise with kvm_arch_prepare_memory_region(), as we
+        * prevent memslot modifications on a pVM that has been run.
+        */
+       mutex_lock(&kvm->slots_lock);
        mutex_lock(&kvm->arch.config_lock);
        if (!pkvm_hyp_vm_is_created(kvm))
                ret = __pkvm_create_hyp_vm(kvm);
        mutex_unlock(&kvm->arch.config_lock);
+       mutex_unlock(&kvm->slots_lock);
 
        return ret;
 }