[PATCH gmem] KVM: guest_memfd: Point .owner at the module that exposes /dev/kvm

From: Sean Christopherson
Date: Mon Oct 23 2023 - 18:37:36 EST


Set .owner for guest_memfd file operations so that the KVM module(s) is
is pinned until any files with callbacks back into KVM are completely
freed.

Note, file types that can call into sub-module code, e.g. kvm-intel.ko or
kvm-amd.ko on x86, must use the module pointer passed to kvm_init(), not
THIS_MODULE (which points at kvm.ko). KVM assumes that if /dev/kvm is
reachable, e.g. VMs are active, then the vendor module is loaded.

Opportunistically clean up the kvm_gmem_{init,exit}() mess that got left
behind by commit 0f7e60a5f42a ("kvm: guestmem: do not use a file system").

Link: https://lore.kernel.org/all/20231018204624.1905300-2-seanjc@xxxxxxxxxx
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---

See the link for details. I'm going to eventually squash this so I put the
bare minimum copy+paste effort into the changelog.

virt/kvm/guest_memfd.c | 7 ++++++-
virt/kvm/kvm_main.c | 2 ++
virt/kvm/kvm_mm.h | 10 ++--------
3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index 9ffce54555ae..94bc478c26f3 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -285,12 +285,17 @@ static struct file *kvm_gmem_get_file(struct kvm_memory_slot *slot)
return file;
}

-static const struct file_operations kvm_gmem_fops = {
+static struct file_operations kvm_gmem_fops = {
.open = generic_file_open,
.release = kvm_gmem_release,
.fallocate = kvm_gmem_fallocate,
};

+void kvm_gmem_init(struct module *module)
+{
+ kvm_gmem_fops.owner = module;
+}
+
static int kvm_gmem_migrate_folio(struct address_space *mapping,
struct folio *dst, struct folio *src,
enum migrate_mode mode)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 959e866c84f0..357b9d9d0225 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -6459,6 +6459,8 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, struct module *module)
if (WARN_ON_ONCE(r))
goto err_vfio;

+ kvm_gmem_init(module);
+
/*
* Registration _must_ be the very last thing done, as this exposes
* /dev/kvm to userspace, i.e. all infrastructure must be setup!
diff --git a/virt/kvm/kvm_mm.h b/virt/kvm/kvm_mm.h
index 798f20d612bb..cca5372b9d5d 100644
--- a/virt/kvm/kvm_mm.h
+++ b/virt/kvm/kvm_mm.h
@@ -38,19 +38,13 @@ static inline void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm,
#endif /* HAVE_KVM_PFNCACHE */

#ifdef CONFIG_KVM_PRIVATE_MEM
-int kvm_gmem_init(void);
-void kvm_gmem_exit(void);
+void kvm_gmem_init(struct module *module);
int kvm_gmem_create(struct kvm *kvm, struct kvm_create_guest_memfd *args);
int kvm_gmem_bind(struct kvm *kvm, struct kvm_memory_slot *slot,
unsigned int fd, loff_t offset);
void kvm_gmem_unbind(struct kvm_memory_slot *slot);
#else
-static inline int kvm_gmem_init(void)
-{
- return 0;
-}
-
-static inline void kvm_gmem_exit(void)
+static inline void kvm_gmem_init(struct module *module)
{

}

base-commit: 911b515af3ec5f53992b9cc162cf7d3893c2fbe2
--
2.42.0.758.gaed0368e0e-goog