]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Reject guest_memfd memslots when the VM has MTE
authorAlexandru Elisei <alexandru.elisei@arm.com>
Wed, 22 Jul 2026 09:03:54 +0000 (10:03 +0100)
committerMarc Zyngier <maz@kernel.org>
Thu, 23 Jul 2026 08:57:06 +0000 (09:57 +0100)
The user cannot use MTE on VMAs created by mapping a guest_memfd file,
as arch_calc_vm_flag_bits() does not set VM_MTE_ALLOWED.

When creating a guest_memfd backed memslot,
kvm_arch_prepare_memory_region() rejects the memslot if MTE is enabled for
the VM and if guest_memfd has been mapped in a VMA that intersects the
memslot.

However, the documentation for KVM_SET_USER_MEMORY_REGION2 explicitly
states that the only condition for userspace_addr is for it to be a legal
userspace address, but the mapping is not required to be valid nor
populated at memslot creation.

If userspace sets userspace_addr to an address that hasn't been mapped, or
if userspace_addr belongs to a VMA that isn't backed by the guest_memfd
file, or if the VMA doesn't intersect the memslot, memslot creation is
successful and KVM ends up with a VM with MTE and guest_memfd-backed
memslots.

The same happens if the order is reversed: when userspace enables MTE, KVM
does not check if memslots backed by guest_memfd are already present.

Fix both issues by rejecting guest_memfd-backed memslots when MTE is
enabled, and by rejecting MTE when guest_memfd-backed memslots are already
present.

Fixes: 32e200bd6e44 ("KVM: arm64: Enable support for guest_memfd backed memory")
Tested-by: Fuad Tabba <fuad.tabba@linux.dev>
Reviewed-by: Fuad Tabba <fuad.tabba@linux.dev>
Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
Link: https://patch.msgid.link/20260722090354.94245-1-alexandru.elisei@arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
Documentation/virt/kvm/api.rst
arch/arm64/kvm/arm.c
arch/arm64/kvm/mmu.c

index a5f9ee92f43e8d6e1137c7fd22eb2db36553137e..e3003a241d5b0a4856e3a4d4b0751474eed40265 100644 (file)
@@ -8414,6 +8414,12 @@ When this capability is enabled all memory in memslots must be mapped as
 attempts to create a memslot with an invalid mmap will result in an
 -EINVAL return.
 
+``guest_memfd``, even though it is an anonymous file, is not supported with MTE.
+Attempting to create a memslot backed by ``guest_memfd`` when the MTE capability
+is enabled, or attempting to enable the MTE capability after
+``guest_memfd``-backed memslots have been created, will result in an -EINVAL
+return.
+
 When enabled the VMM may make use of the ``KVM_ARM_MTE_COPY_TAGS`` ioctl to
 perform a bulk copy of tags to/from the guest.
 
index 50adfff75be82ed452c2b3e281be54e74cca097b..9a6c72a186727b5d7a8c323d383fa531c4fe1710 100644 (file)
@@ -149,14 +149,27 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
                set_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
                        &kvm->arch.flags);
                break;
-       case KVM_CAP_ARM_MTE:
-               mutex_lock(&kvm->lock);
-               if (system_supports_mte() && !kvm->created_vcpus) {
-                       r = 0;
-                       set_bit(KVM_ARCH_FLAG_MTE_ENABLED, &kvm->arch.flags);
+       case KVM_CAP_ARM_MTE: {
+               struct kvm_memory_slot *memslot;
+               int bkt;
+
+               guard(mutex)(&kvm->lock);
+               if (!system_supports_mte() || kvm->created_vcpus)
+                       break;
+
+               r = 0;
+               guard(mutex)(&kvm->slots_lock);
+               kvm_for_each_memslot(memslot, bkt, kvm_memslots(kvm)) {
+                       if (kvm_slot_has_gmem(memslot)) {
+                               r = -EINVAL;
+                               break;
+                       }
                }
-               mutex_unlock(&kvm->lock);
+               if (r == 0)
+                       set_bit(KVM_ARCH_FLAG_MTE_ENABLED, &kvm->arch.flags);
                break;
+
+       }
        case KVM_CAP_ARM_SYSTEM_SUSPEND:
                r = 0;
                set_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags);
index 6c941aaa10c639b87ca7ae27201b2eafccae1a5e..2d95203386baa4a3d570caa5c91bd66f1d17dc30 100644 (file)
@@ -2652,6 +2652,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
        if (kvm_slot_has_gmem(new) && !kvm_memslot_is_gmem_only(new))
                return -EINVAL;
 
+       /* guest_memfd is incompatible with MTE. */
+       if (kvm_slot_has_gmem(new) && kvm_has_mte(kvm))
+               return -EINVAL;
+
        hva = new->userspace_addr;
        reg_end = hva + (new->npages << PAGE_SHIFT);