Skip to content

Commit 95cc9e7

Browse files
YsuOSbonzini
authored andcommitted
x86/kvm: Avoid freeing stack-allocated node in kvm_async_pf_queue_task
kvm_async_pf_queue_task() can incorrectly try to kfree() a node allocated on the stack of kvm_async_pf_task_wait_schedule(). This occurs when a task requests a PF while another task's PF request with the same token is still pending. Since the token is derived from the (u32)address in exc_page_fault(), two different tasks can generate the same token. Currently, kvm_async_pf_queue_task() assumes that any entry found in the list is a dummy entry and tries to kfree() it. To fix this, add a flag to the node structure to distinguish stack-allocated nodes, and only kfree() the node if it is a dummy entry. Signed-off-by: Ryosuke Yasuoka <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent c8ebd43 commit 95cc9e7

1 file changed

Lines changed: 16 additions & 3 deletions

File tree

arch/x86/kernel/kvm.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct kvm_task_sleep_node {
8989
struct swait_queue_head wq;
9090
u32 token;
9191
int cpu;
92+
bool dummy;
9293
};
9394

9495
static struct kvm_task_sleep_head {
@@ -120,15 +121,26 @@ static bool kvm_async_pf_queue_task(u32 token, struct kvm_task_sleep_node *n)
120121
raw_spin_lock(&b->lock);
121122
e = _find_apf_task(b, token);
122123
if (e) {
123-
/* dummy entry exist -> wake up was delivered ahead of PF */
124-
hlist_del(&e->link);
124+
struct kvm_task_sleep_node *dummy = NULL;
125+
126+
/*
127+
* The entry can either be a 'dummy' entry (which is put on the
128+
* list when wake-up happens ahead of APF handling completion)
129+
* or a token from another task which should not be touched.
130+
*/
131+
if (e->dummy) {
132+
hlist_del(&e->link);
133+
dummy = e;
134+
}
135+
125136
raw_spin_unlock(&b->lock);
126-
kfree(e);
137+
kfree(dummy);
127138
return false;
128139
}
129140

130141
n->token = token;
131142
n->cpu = smp_processor_id();
143+
n->dummy = false;
132144
init_swait_queue_head(&n->wq);
133145
hlist_add_head(&n->link, &b->list);
134146
raw_spin_unlock(&b->lock);
@@ -231,6 +243,7 @@ static void kvm_async_pf_task_wake(u32 token)
231243
}
232244
dummy->token = token;
233245
dummy->cpu = smp_processor_id();
246+
dummy->dummy = true;
234247
init_swait_queue_head(&dummy->wq);
235248
hlist_add_head(&dummy->link, &b->list);
236249
dummy = NULL;

0 commit comments

Comments
 (0)