From: David Matlack <dmatlack@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: David Matlack <dmatlack@google.com>,
"open list:KERNEL VIRTUAL MACHINE (KVM)" <kvm@vger.kernel.org>,
Marcelo Tosatti <mtosatti@redhat.com>,
seanjc@google.com, bgardon@google.com
Subject: [PATCH v2 0/2] KVM: Prevent module exit until all VMs are freed
Date: Wed, 9 Mar 2022 21:32:06 +0000 [thread overview]
Message-ID: <20220309213208.872644-1-dmatlack@google.com> (raw)
This series fixes a long-standing theoretical bug where the KVM module
can be unloaded while there are still references to a struct kvm. This
can be reproduced with a simple patch [1] to run some delayed work 10
seconds after a VM file descriptor is released.
This bug was originally fixed by Ben Gardon <bgardon@google.com> in
Google's kernel due to a race with an internal kernel daemon.
KVM's async_pf code looks susceptible to this race since its inception,
but clearly no one has noticed. Upcoming changes to the TDP MMU will
move zapping to asynchronous workers which is much more likely to hit
this issue. Fix it now to close the gap in async_pf and prepare for the
TDP MMU zapping changes.
While here I noticed some further cleanups that could be done in the
async_pf code. It seems unnecessary for the async_pf code to grab a
reference via kvm_get_kvm() because there's code to synchronously drain
its queue of work in kvm_destroy_vm() -> ... ->
kvm_clear_async_pf_completion_queue() (at least on x86). This is
actually dead code because kvm_destroy_vm() will never be called while
there are references to kvm.users_count (which the async_pf callbacks
themselves hold). It seems we could either drop the reference grabbing
in async_pf.c or drop the call to kvm_clear_async_pf_completion_queue().
These patches apply on the latest kvm/queue commit b13a3befc815 ("KVM:
selftests: Add test to populate a VM with the max possible guest mem")
after reverting commit c9bdd0aa6800 ("KVM: allow struct kvm to outlive
the file descriptors").
v2:
- Add comment explaining try variant [Sean]
- Additional fixes commit to clarify bug not limited to async_pf [Sean]
- Collect R-b tags.
v1: https://lore.kernel.org/kvm/20220303183328.1499189-1-dmatlack@google.com/
[1] To repro: Apply the following patch, run a KVM selftest, and then
unload the KVM module within 10 seconds of the selftest finishing. The
kernel will panic. With the fix applied, module unloading will fail
until the final struct kvm reference is put.
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 9536ffa0473b..db827cf6a7a7 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -771,6 +771,8 @@ struct kvm {
struct notifier_block pm_notifier;
#endif
char stats_id[KVM_STATS_NAME_SIZE];
+
+ struct delayed_work run_after_vm_release_work;
};
#define kvm_err(fmt, ...) \
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 64eb99444688..35ae6d32dae5 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1258,12 +1258,25 @@ void kvm_put_kvm_no_destroy(struct kvm *kvm)
}
EXPORT_SYMBOL_GPL(kvm_put_kvm_no_destroy);
+static void run_after_vm_release(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct kvm *kvm = container_of(dwork, struct kvm, run_after_vm_release_work);
+
+ pr_info("I'm still alive!\n");
+ kvm_put_kvm(kvm);
+}
+
static int kvm_vm_release(struct inode *inode, struct file *filp)
{
struct kvm *kvm = filp->private_data;
kvm_irqfd_release(kvm);
+ kvm_get_kvm(kvm);
+ INIT_DELAYED_WORK(&kvm->run_after_vm_release_work, run_after_vm_release);
+ schedule_delayed_work(&kvm->run_after_vm_release_work, 10 * HZ);
+
kvm_put_kvm(kvm);
return 0;
}
David Matlack (2):
KVM: Prevent module exit until all VMs are freed
Revert "KVM: set owner of cpu and vm file operations"
virt/kvm/kvm_main.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
base-commit: ce41d078aaa9cf15cbbb4a42878cc6160d76525e
--
2.35.1.616.g0bdcbb4464-goog
next reply other threads:[~2022-03-09 21:32 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-09 21:32 David Matlack [this message]
2022-03-09 21:32 ` [PATCH v2 1/2] KVM: Prevent module exit until all VMs are freed David Matlack
2022-03-09 21:32 ` [PATCH v2 2/2] Revert "KVM: set owner of cpu and vm file operations" David Matlack
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220309213208.872644-1-dmatlack@google.com \
--to=dmatlack@google.com \
--cc=bgardon@google.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox