]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Check whether a VM IOCTL is allowed in pKVM
authorFuad Tabba <tabba@google.com>
Thu, 11 Dec 2025 10:47:08 +0000 (10:47 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 15 Jan 2026 15:55:50 +0000 (15:55 +0000)
Certain VM IOCTLs are tied to specific VM features. Since pKVM does not
support all features, restrict which IOCTLs are allowed depending on
whether the associated feature is supported.

Use the existing VM capability check as the source of truth to whether
an IOCTL is allowed for a particular VM by mapping the IOCTLs with their
associated capabilities.

Suggested-by: Oliver Upton <oupton@kernel.org>
Signed-off-by: Fuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20251211104710.151771-9-tabba@google.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/kvm_pkvm.h
arch/arm64/kvm/arm.c

index 09a7599716531e2d6673dc48b7f009f647d2dd3a..757076ad4ec92fdc4056180a246b475964939aad 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/arm_ffa.h>
 #include <linux/memblock.h>
 #include <linux/scatterlist.h>
+#include <asm/kvm_host.h>
 #include <asm/kvm_pgtable.h>
 
 /* Maximum number of VMs that can co-exist under pKVM. */
@@ -51,6 +52,25 @@ static inline bool kvm_pkvm_ext_allowed(struct kvm *kvm, long ext)
        }
 }
 
+/*
+ * Check whether the KVM VM IOCTL is allowed in pKVM.
+ *
+ * Certain features are allowed only for non-protected VMs in pKVM, which is why
+ * this takes the VM (kvm) as a parameter.
+ */
+static inline bool kvm_pkvm_ioctl_allowed(struct kvm *kvm, unsigned int ioctl)
+{
+       long ext;
+       int r;
+
+       r = kvm_get_cap_for_kvm_ioctl(ioctl, &ext);
+
+       if (WARN_ON_ONCE(r < 0))
+               return false;
+
+       return kvm_pkvm_ext_allowed(kvm, ext);
+}
+
 extern struct memblock_region kvm_nvhe_sym(hyp_memory)[];
 extern unsigned int kvm_nvhe_sym(hyp_memblock_nr);
 
index 7492744831856692d3e51c71f1066bc7d1dbee3a..a5d48bae8f6ac618ab29f567b08bbc22e877ae38 100644 (file)
@@ -1938,6 +1938,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
        void __user *argp = (void __user *)arg;
        struct kvm_device_attr attr;
 
+       if (is_protected_kvm_enabled() && !kvm_pkvm_ioctl_allowed(kvm, ioctl))
+               return -EINVAL;
+
        switch (ioctl) {
        case KVM_CREATE_IRQCHIP: {
                int ret;