From: Fuad Tabba Date: Thu, 11 Dec 2025 10:47:08 +0000 (+0000) Subject: KVM: arm64: Check whether a VM IOCTL is allowed in pKVM X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b12b3b04f6ba072ca5a618a75e546c996be94bd1;p=thirdparty%2Fkernel%2Fstable.git KVM: arm64: Check whether a VM IOCTL is allowed in pKVM 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 Signed-off-by: Fuad Tabba Link: https://patch.msgid.link/20251211104710.151771-9-tabba@google.com Signed-off-by: Marc Zyngier --- diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h index 09a759971653..757076ad4ec9 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -9,6 +9,7 @@ #include #include #include +#include #include /* 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); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 749274483185..a5d48bae8f6a 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -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;