[PATCH v9 08/17] KVM: guest_memfd: Check that userspace_addr and fd+offset refer to same range

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ackerley Tng <ackerleytng@xxxxxxxxxx>

On binding of a guest_memfd with a memslot, check that the slot's
userspace_addr and the requested fd and offset refer to the same memory
range.

This check is best-effort: nothing prevents userspace from later mapping
other memory to the same provided in slot->userspace_addr and breaking
guest operation.

Suggested-by: David Hildenbrand <david@xxxxxxxxxx>
Suggested-by: Sean Christopherson <seanjc@xxxxxxxxxx>
Suggested-by: Yan Zhao <yan.y.zhao@xxxxxxxxx>
Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
Signed-off-by: Fuad Tabba <tabba@xxxxxxxxxx>
---
 virt/kvm/guest_memfd.c | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 8e6d1866b55e..2f499021df66 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -556,6 +556,32 @@ int kvm_gmem_create(struct kvm *kvm, struct kvm_create_guest_memfd *args)
 	return __kvm_gmem_create(kvm, size, flags);
 }
 
+static bool kvm_gmem_is_same_range(struct kvm *kvm,
+				   struct kvm_memory_slot *slot,
+				   struct file *file, loff_t offset)
+{
+	struct mm_struct *mm = kvm->mm;
+	loff_t userspace_addr_offset;
+	struct vm_area_struct *vma;
+	bool ret = false;
+
+	mmap_read_lock(mm);
+
+	vma = vma_lookup(mm, slot->userspace_addr);
+	if (!vma)
+		goto out;
+
+	if (vma->vm_file != file)
+		goto out;
+
+	userspace_addr_offset = slot->userspace_addr - vma->vm_start;
+	ret = userspace_addr_offset + (vma->vm_pgoff << PAGE_SHIFT) == offset;
+out:
+	mmap_read_unlock(mm);
+
+	return ret;
+}
+
 int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot,
 		  unsigned int fd, loff_t offset)
 {
@@ -585,9 +611,14 @@ int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot,
 	    offset + size > i_size_read(inode))
 		goto err;
 
-	if (kvm_gmem_supports_shared(inode) &&
-	    !kvm_arch_vm_supports_gmem_shared_mem(kvm))
-		goto err;
+	if (kvm_gmem_supports_shared(inode)) {
+		if (!kvm_arch_vm_supports_gmem_shared_mem(kvm))
+			goto err;
+
+		if (slot->userspace_addr &&
+		    !kvm_gmem_is_same_range(kvm, slot, file, offset))
+			goto err;
+	}
 
 	filemap_invalidate_lock(inode->i_mapping);
 
-- 
2.49.0.1045.g170613ef41-goog





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux