@@ -177,6 +177,7 @@ struct DeviceState {
char *canonical_path;
bool realized;
bool pending_deleted_event;
+ bool in_mmio;
QemuOpts *opts;
int hotplugged;
bool allow_unplug_during_migration;
@@ -1410,8 +1410,20 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
return MEMTX_DECODE_ERROR;
}
+ if (mr->dev) {
+ if (mr->dev->in_mmio) {
+ return MEMTX_ERROR;
+ } else {
+ mr->dev->in_mmio = true;
+ }
+ }
+
r = memory_region_dispatch_read1(mr, addr, pval, size, attrs);
adjust_endianness(mr, pval, op);
+
+ if (mr->dev) {
+ mr->dev->in_mmio = false;
+ }
return r;
}
@@ -1448,6 +1460,7 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
MemTxAttrs attrs)
{
unsigned size = memop_size(op);
+ MemTxResult ret;
if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
unassigned_mem_write(mr, addr, data, size);
@@ -1461,20 +1474,32 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
return MEMTX_OK;
}
+ if (mr->dev) {
+ if (mr->dev->in_mmio) {
+ return MEMTX_ERROR;
+ } else {
+ mr->dev->in_mmio = true;
+ }
+ }
+
if (mr->ops->write) {
- return access_with_adjusted_size(addr, &data, size,
+ ret = access_with_adjusted_size(addr, &data, size,
mr->ops->impl.min_access_size,
mr->ops->impl.max_access_size,
memory_region_write_accessor, mr,
attrs);
} else {
- return
- access_with_adjusted_size(addr, &data, size,
+ ret = access_with_adjusted_size(addr, &data, size,
mr->ops->impl.min_access_size,
mr->ops->impl.max_access_size,
memory_region_write_with_attrs_accessor,
mr, attrs);
}
+ if (mr->dev) {
+ mr->dev->in_mmio = false;
+ }
+
+ return ret;
}
void memory_region_init_io(MemoryRegion *mr,
This patch adds a 'in_mmio' flag to 'DeviceState' to indicate that the device is doing MMIO path. This can avoid the malicious guest do DMA to MMIO and crash the qemu. Signed-off-by: Li Qiang <liq3ea@163.com> --- include/hw/qdev-core.h | 1 + softmmu/memory.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-)