[PATCH v4 7/8] KVM: arm64: Check whether a VM IOCTL is allowed in pKVM
Fuad Tabba
tabba at google.com
Wed Nov 12 02:51:58 PST 2025
Hi Oliver,
On Wed, 12 Nov 2025 at 10:07, Oliver Upton <oupton at kernel.org> wrote:
>
> Hi Fuad,
>
> On Wed, Nov 12, 2025 at 09:20:50AM +0000, Fuad Tabba wrote:
> > +/*
> > + * 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)
> > +{
> > + switch (ioctl) {
> > + case KVM_CREATE_IRQCHIP:
> > + return kvm_pkvm_ext_allowed(kvm, KVM_CAP_IRQCHIP);
> > + case KVM_ARM_SET_DEVICE_ADDR:
> > + return kvm_pkvm_ext_allowed(kvm, KVM_CAP_ARM_SET_DEVICE_ADDR);
> > + case KVM_ARM_MTE_COPY_TAGS:
> > + return kvm_pkvm_ext_allowed(kvm, KVM_CAP_ARM_MTE);
> > + case KVM_ARM_SET_COUNTER_OFFSET:
> > + return kvm_pkvm_ext_allowed(kvm, KVM_CAP_COUNTER_OFFSET);
> > + case KVM_HAS_DEVICE_ATTR:
> > + case KVM_SET_DEVICE_ATTR:
> > + case KVM_GET_DEVICE_ATTR:
> > + return kvm_pkvm_ext_allowed(kvm, KVM_CAP_DEVICE_CTRL) ||
> > + kvm_pkvm_ext_allowed(kvm, KVM_CAP_VM_ATTRIBUTES);
> > + case KVM_ARM_GET_REG_WRITABLE_MASKS:
> > + return kvm_pkvm_ext_allowed(kvm, KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES);
> > + default:
> > + return true;
> > + }
> > +}
> > +
>
> I was thinking of something a bit more tabular since CCA will impose its
> own restrictions + pKVM could share the ioctl <=> KVM_CAP association.
Sure. Before I respin, how about something along these lines:
struct kvm_ioctl_cap_map {
unsigned int ioctl;
long ext;
};
/*
* Sorted by ioctl to allow for potential binary search,
* though linear scan is sufficient for this size.
* (Note to Oliver: If you like, I can add a runtime check if we want
to support binary search.)
*/
static const struct kvm_ioctl_cap_map vm_ioctl_caps[] = {
{ KVM_CREATE_IRQCHIP, KVM_CAP_IRQCHIP },
{ KVM_ARM_SET_DEVICE_ADDR, KVM_CAP_ARM_SET_DEVICE_ADDR },
{ KVM_ARM_MTE_COPY_TAGS, KVM_CAP_ARM_MTE },
{ KVM_SET_DEVICE_ATTR, KVM_CAP_DEVICE_CTRL },
{ KVM_GET_DEVICE_ATTR, KVM_CAP_DEVICE_CTRL },
{ KVM_HAS_DEVICE_ATTR, KVM_CAP_DEVICE_CTRL },
{ KVM_ARM_SET_COUNTER_OFFSET, KVM_CAP_COUNTER_OFFSET },
{ KVM_ARM_GET_REG_WRITABLE_MASKS, KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES },
{ KVM_ARM_PREFERRED_TARGET, -1 }, /* Basic IOCTLs, no gating capability */
};
/*
* Set *ext to the capability, which is -1 for basic capabilities.
* Return 0 if found, or -EINVAL if no IOCTL matches.
*/
long kvm_get_cap_for_kvm_ioctl(unsigned int ioctl, long *ext)
{
int i;
for (i = 0; i < ARRAY_SIZE(vm_ioctl_caps); i++) {
if (vm_ioctl_caps[i]. ioctl == ioctl)
*ext = vm_ioctl_caps[i].ext;
return 0;
}
return -EINVAL;
}
> Anyway, ioctl filtering should be an allowlist (default to false) just
> like kvm_pkvm_ext_allowed(). The default assumption is that new UAPI is not
> supported for pVMs unless explicitly stated otherwise.
Of course, that's what we do with capability checks.
Thanks,
/fuad
> Thanks,
> Oliver
More information about the linux-arm-kernel
mailing list