|
|
2be4b2 |
From a1ead07b6a0facefafb959542f3088f427c7eb2d Mon Sep 17 00:00:00 2001
|
|
|
73b8f2 |
From: Frediano Ziglio <fziglio@redhat.com>
|
|
|
73b8f2 |
Date: Tue, 8 Sep 2015 12:12:19 +0100
|
|
|
2be4b2 |
Subject: [PATCH 57/64] Fix race condition in red_get_data_chunks_ptr
|
|
|
73b8f2 |
|
|
|
73b8f2 |
Do not read multiple times data from guest as this can be changed by
|
|
|
73b8f2 |
other guest vcpus. This causes races and security problems if these
|
|
|
73b8f2 |
data are used for buffer allocation or checks.
|
|
|
73b8f2 |
|
|
|
73b8f2 |
Actually, the 'data' member can't change during read as it is just a
|
|
|
73b8f2 |
pointer to a fixed array contained in qxl. However, this change will
|
|
|
73b8f2 |
make it clear that there can be no race condition.
|
|
|
73b8f2 |
|
|
|
73b8f2 |
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
|
|
|
73b8f2 |
---
|
|
|
73b8f2 |
server/red_parse_qxl.c | 17 ++++++++++-------
|
|
|
73b8f2 |
1 file changed, 10 insertions(+), 7 deletions(-)
|
|
|
73b8f2 |
|
|
|
73b8f2 |
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
|
|
|
73b8f2 |
index c4b82be..7cc20e6 100644
|
|
|
73b8f2 |
--- a/server/red_parse_qxl.c
|
|
|
73b8f2 |
+++ b/server/red_parse_qxl.c
|
|
|
73b8f2 |
@@ -102,30 +102,33 @@ static size_t red_get_data_chunks_ptr(RedMemSlotInfo *slots, int group_id,
|
|
|
73b8f2 |
RedDataChunk *red_prev;
|
|
|
73b8f2 |
size_t data_size = 0;
|
|
|
73b8f2 |
int error;
|
|
|
73b8f2 |
+ QXLPHYSICAL next_chunk;
|
|
|
73b8f2 |
|
|
|
73b8f2 |
red->data_size = qxl->data_size;
|
|
|
73b8f2 |
data_size += red->data_size;
|
|
|
73b8f2 |
- if (!validate_virt(slots, (intptr_t)qxl->data, memslot_id, red->data_size, group_id)) {
|
|
|
73b8f2 |
+ red->data = qxl->data;
|
|
|
73b8f2 |
+ if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
|
|
|
73b8f2 |
+ red->data = NULL;
|
|
|
73b8f2 |
return 0;
|
|
|
73b8f2 |
}
|
|
|
73b8f2 |
- red->data = qxl->data;
|
|
|
73b8f2 |
red->prev_chunk = NULL;
|
|
|
73b8f2 |
|
|
|
73b8f2 |
- while (qxl->next_chunk) {
|
|
|
73b8f2 |
+ while ((next_chunk = qxl->next_chunk) != 0) {
|
|
|
73b8f2 |
red_prev = red;
|
|
|
73b8f2 |
red = spice_new(RedDataChunk, 1);
|
|
|
73b8f2 |
- memslot_id = get_memslot_id(slots, qxl->next_chunk);
|
|
|
73b8f2 |
- qxl = (QXLDataChunk *)get_virt(slots, qxl->next_chunk, sizeof(*qxl), group_id,
|
|
|
73b8f2 |
+ memslot_id = get_memslot_id(slots, next_chunk);
|
|
|
73b8f2 |
+ qxl = (QXLDataChunk *)get_virt(slots, next_chunk, sizeof(*qxl), group_id,
|
|
|
73b8f2 |
&error);
|
|
|
73b8f2 |
if (error) {
|
|
|
73b8f2 |
return 0;
|
|
|
73b8f2 |
}
|
|
|
73b8f2 |
red->data_size = qxl->data_size;
|
|
|
73b8f2 |
data_size += red->data_size;
|
|
|
73b8f2 |
- if (!validate_virt(slots, (intptr_t)qxl->data, memslot_id, red->data_size, group_id)) {
|
|
|
73b8f2 |
+ red->data = qxl->data;
|
|
|
73b8f2 |
+ if (!validate_virt(slots, (intptr_t)red->data, memslot_id, red->data_size, group_id)) {
|
|
|
73b8f2 |
+ red->data = NULL;
|
|
|
73b8f2 |
return 0;
|
|
|
73b8f2 |
}
|
|
|
73b8f2 |
- red->data = qxl->data;
|
|
|
73b8f2 |
red->prev_chunk = red_prev;
|
|
|
73b8f2 |
red_prev->next_chunk = red;
|
|
|
73b8f2 |
}
|
|
|
73b8f2 |
--
|
|
|
73b8f2 |
2.4.3
|
|
|
73b8f2 |
|