kvm_async_pf_queue_task() can incorrectly remove a node allocated on the stack of kvm_async_pf_task_wait_schedule(). This occurs when a task request a PF while another task's PF request with the same token is still pending. Currently, kvm_async_pf_queue_task() assumes that any entry in the list is a dummy entry and tries to kfree(). To fix this, add a dummy flag to the node structure and the function should check this flag and kfree() only if it is a dummy entry. Signed-off-by: Ryosuke Yasuoka --- arch/x86/kernel/kvm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index b67d7c59dca0..2c92ec528379 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -88,6 +88,7 @@ struct kvm_task_sleep_node { struct swait_queue_head wq; u32 token; int cpu; + bool dummy; }; static struct kvm_task_sleep_head { @@ -119,10 +120,17 @@ static bool kvm_async_pf_queue_task(u32 token, struct kvm_task_sleep_node *n) raw_spin_lock(&b->lock); e = _find_apf_task(b, token); if (e) { + struct kvm_task_sleep_node *dummy = NULL; + /* dummy entry exist -> wake up was delivered ahead of PF */ - hlist_del(&e->link); + /* Otherwise it should not be freed here. */ + if (e->dummy) { + hlist_del(&e->link); + dummy = e; + } + raw_spin_unlock(&b->lock); - kfree(e); + kfree(dummy); return false; } @@ -230,6 +238,7 @@ static void kvm_async_pf_task_wake(u32 token) } dummy->token = token; dummy->cpu = smp_processor_id(); + dummy->dummy = true; init_swait_queue_head(&dummy->wq); hlist_add_head(&dummy->link, &b->list); dummy = NULL; base-commit: 2eba5e05d9bcf4cdea995ed51b0f07ba0275794a -- 2.51.0