mirror of
https://git.proxmox.com/git/qemu
synced 2025-08-07 18:13:00 +00:00
qxl: don't abort on guest trigerrable ring indices mismatch
Signed-off-by: Alon Levy <alevy@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
2fce7edf46
commit
0b81c478cf
51
hw/qxl.c
51
hw/qxl.c
@ -27,28 +27,42 @@
|
|||||||
|
|
||||||
#include "qxl.h"
|
#include "qxl.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: SPICE_RING_PROD_ITEM accesses memory on the pci bar and as
|
||||||
|
* such can be changed by the guest, so to avoid a guest trigerrable
|
||||||
|
* abort we just set qxl_guest_bug and set the return to NULL. Still
|
||||||
|
* it may happen as a result of emulator bug as well.
|
||||||
|
*/
|
||||||
#undef SPICE_RING_PROD_ITEM
|
#undef SPICE_RING_PROD_ITEM
|
||||||
#define SPICE_RING_PROD_ITEM(r, ret) { \
|
#define SPICE_RING_PROD_ITEM(qxl, r, ret) { \
|
||||||
typeof(r) start = r; \
|
typeof(r) start = r; \
|
||||||
typeof(r) end = r + 1; \
|
typeof(r) end = r + 1; \
|
||||||
uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
|
uint32_t prod = (r)->prod & SPICE_RING_INDEX_MASK(r); \
|
||||||
typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
|
typeof(&(r)->items[prod]) m_item = &(r)->items[prod]; \
|
||||||
if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||||
abort(); \
|
qxl_guest_bug(qxl, "SPICE_RING_PROD_ITEM indices mismatch " \
|
||||||
} \
|
"! %p <= %p < %p", (uint8_t *)start, \
|
||||||
|
(uint8_t *)m_item, (uint8_t *)end); \
|
||||||
|
ret = NULL; \
|
||||||
|
} else { \
|
||||||
ret = &m_item->el; \
|
ret = &m_item->el; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SPICE_RING_CONS_ITEM
|
#undef SPICE_RING_CONS_ITEM
|
||||||
#define SPICE_RING_CONS_ITEM(r, ret) { \
|
#define SPICE_RING_CONS_ITEM(qxl, r, ret) { \
|
||||||
typeof(r) start = r; \
|
typeof(r) start = r; \
|
||||||
typeof(r) end = r + 1; \
|
typeof(r) end = r + 1; \
|
||||||
uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
|
uint32_t cons = (r)->cons & SPICE_RING_INDEX_MASK(r); \
|
||||||
typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
|
typeof(&(r)->items[cons]) m_item = &(r)->items[cons]; \
|
||||||
if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
if (!((uint8_t*)m_item >= (uint8_t*)(start) && (uint8_t*)(m_item + 1) <= (uint8_t*)(end))) { \
|
||||||
abort(); \
|
qxl_guest_bug(qxl, "SPICE_RING_CONS_ITEM indices mismatch " \
|
||||||
} \
|
"! %p <= %p < %p", (uint8_t *)start, \
|
||||||
|
(uint8_t *)m_item, (uint8_t *)end); \
|
||||||
|
ret = NULL; \
|
||||||
|
} else { \
|
||||||
ret = &m_item->el; \
|
ret = &m_item->el; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ALIGN
|
#undef ALIGN
|
||||||
@ -343,7 +357,8 @@ static void init_qxl_ram(PCIQXLDevice *d)
|
|||||||
SPICE_RING_INIT(&d->ram->cmd_ring);
|
SPICE_RING_INIT(&d->ram->cmd_ring);
|
||||||
SPICE_RING_INIT(&d->ram->cursor_ring);
|
SPICE_RING_INIT(&d->ram->cursor_ring);
|
||||||
SPICE_RING_INIT(&d->ram->release_ring);
|
SPICE_RING_INIT(&d->ram->release_ring);
|
||||||
SPICE_RING_PROD_ITEM(&d->ram->release_ring, item);
|
SPICE_RING_PROD_ITEM(d, &d->ram->release_ring, item);
|
||||||
|
assert(item);
|
||||||
*item = 0;
|
*item = 0;
|
||||||
qxl_ring_set_dirty(d);
|
qxl_ring_set_dirty(d);
|
||||||
}
|
}
|
||||||
@ -559,8 +574,10 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
|
|||||||
if (SPICE_RING_IS_EMPTY(ring)) {
|
if (SPICE_RING_IS_EMPTY(ring)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
|
SPICE_RING_CONS_ITEM(qxl, ring, cmd);
|
||||||
SPICE_RING_CONS_ITEM(ring, cmd);
|
if (!cmd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ext->cmd = *cmd;
|
ext->cmd = *cmd;
|
||||||
ext->group_id = MEMSLOT_GROUP_GUEST;
|
ext->group_id = MEMSLOT_GROUP_GUEST;
|
||||||
ext->flags = qxl->cmdflags;
|
ext->flags = qxl->cmdflags;
|
||||||
@ -572,6 +589,7 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
|
|||||||
qxl->guest_primary.commands++;
|
qxl->guest_primary.commands++;
|
||||||
qxl_track_command(qxl, ext);
|
qxl_track_command(qxl, ext);
|
||||||
qxl_log_command(qxl, "cmd", ext);
|
qxl_log_command(qxl, "cmd", ext);
|
||||||
|
trace_qxl_ring_command_get(qxl->id, qxl_mode_to_string(qxl->mode));
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -630,7 +648,10 @@ static inline void qxl_push_free_res(PCIQXLDevice *d, int flush)
|
|||||||
if (notify) {
|
if (notify) {
|
||||||
qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
|
qxl_send_events(d, QXL_INTERRUPT_DISPLAY);
|
||||||
}
|
}
|
||||||
SPICE_RING_PROD_ITEM(ring, item);
|
SPICE_RING_PROD_ITEM(d, ring, item);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
*item = 0;
|
*item = 0;
|
||||||
d->num_free_res = 0;
|
d->num_free_res = 0;
|
||||||
d->last_release = NULL;
|
d->last_release = NULL;
|
||||||
@ -656,7 +677,10 @@ static void interface_release_resource(QXLInstance *sin,
|
|||||||
* pci bar 0, $command.release_info
|
* pci bar 0, $command.release_info
|
||||||
*/
|
*/
|
||||||
ring = &qxl->ram->release_ring;
|
ring = &qxl->ram->release_ring;
|
||||||
SPICE_RING_PROD_ITEM(ring, item);
|
SPICE_RING_PROD_ITEM(qxl, ring, item);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (*item == 0) {
|
if (*item == 0) {
|
||||||
/* stick head into the ring */
|
/* stick head into the ring */
|
||||||
id = ext.info->id;
|
id = ext.info->id;
|
||||||
@ -695,7 +719,10 @@ static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *
|
|||||||
if (SPICE_RING_IS_EMPTY(ring)) {
|
if (SPICE_RING_IS_EMPTY(ring)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SPICE_RING_CONS_ITEM(ring, cmd);
|
SPICE_RING_CONS_ITEM(qxl, ring, cmd);
|
||||||
|
if (!cmd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ext->cmd = *cmd;
|
ext->cmd = *cmd;
|
||||||
ext->group_id = MEMSLOT_GROUP_GUEST;
|
ext->group_id = MEMSLOT_GROUP_GUEST;
|
||||||
ext->flags = qxl->cmdflags;
|
ext->flags = qxl->cmdflags;
|
||||||
|
Loading…
Reference in New Issue
Block a user