Skip to content

Commit 405294f

Browse files
sean-jcbonzini
authored andcommitted
KVM: Unconditionally get a ref to /dev/kvm module when creating a VM
Unconditionally get a reference to the /dev/kvm module when creating a VM instead of using try_get_module(), which will fail if the module is in the process of being forcefully unloaded. The error handling when try_get_module() fails doesn't properly unwind all that has been done, e.g. doesn't call kvm_arch_pre_destroy_vm() and doesn't remove the VM from the global list. Not removing VMs from the global list tends to be fatal, e.g. leads to use-after-free explosions. The obvious alternative would be to add proper unwinding, but the justification for using try_get_module(), "rmmod --wait", is completely bogus as support for "rmmod --wait", i.e. delete_module() without O_NONBLOCK, was removed by commit 3f2b9c9 ("module: remove rmmod --wait option.") nearly a decade ago. It's still possible for try_get_module() to fail due to the module dying (more like being killed), as the module will be tagged MODULE_STATE_GOING by "rmmod --force", i.e. delete_module(..., O_TRUNC), but playing nice with forced unloading is an exercise in futility and gives a falsea sense of security. Using try_get_module() only prevents acquiring _new_ references, it doesn't magically put the references held by other VMs, and forced unloading doesn't wait, i.e. "rmmod --force" on KVM is all but guaranteed to cause spectacular fireworks; the window where KVM will fail try_get_module() is tiny compared to the window where KVM is building and running the VM with an elevated module refcount. Addressing KVM's inability to play nice with "rmmod --force" is firmly out-of-scope. Forcefully unloading any module taints kernel (for obvious reasons) _and_ requires the kernel to be built with CONFIG_MODULE_FORCE_UNLOAD=y, which is off by default and comes with the amusing disclaimer that it's "mainly for kernel developers and desperate users". In other words, KVM is free to scoff at bug reports due to using "rmmod --force" while VMs may be running. Fixes: 5f6de5c ("KVM: Prevent module exit until all VMs are freed") Cc: [email protected] Cc: David Matlack <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 4ba4f41 commit 405294f

File tree

1 file changed

+4
-10
lines changed

1 file changed

+4
-10
lines changed

virt/kvm/kvm_main.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,9 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname)
11341134
if (!kvm)
11351135
return ERR_PTR(-ENOMEM);
11361136

1137+
/* KVM is pinned via open("/dev/kvm"), the fd passed to this ioctl(). */
1138+
__module_get(kvm_chardev_ops.owner);
1139+
11371140
KVM_MMU_LOCK_INIT(kvm);
11381141
mmgrab(current->mm);
11391142
kvm->mm = current->mm;
@@ -1226,16 +1229,6 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname)
12261229
preempt_notifier_inc();
12271230
kvm_init_pm_notifier(kvm);
12281231

1229-
/*
1230-
* When the fd passed to this ioctl() is opened it pins the module,
1231-
* but try_module_get() also prevents getting a reference if the module
1232-
* is in MODULE_STATE_GOING (e.g. if someone ran "rmmod --wait").
1233-
*/
1234-
if (!try_module_get(kvm_chardev_ops.owner)) {
1235-
r = -ENODEV;
1236-
goto out_err;
1237-
}
1238-
12391232
return kvm;
12401233

12411234
out_err:
@@ -1259,6 +1252,7 @@ static struct kvm *kvm_create_vm(unsigned long type, const char *fdname)
12591252
out_err_no_srcu:
12601253
kvm_arch_free_vm(kvm);
12611254
mmdrop(current->mm);
1255+
module_put(kvm_chardev_ops.owner);
12621256
return ERR_PTR(r);
12631257
}
12641258

0 commit comments

Comments
 (0)