105 lines
3.4 KiB
Diff
105 lines
3.4 KiB
Diff
From 13f4ebe4708f4f4dc20d710e475a42d520459860 Mon Sep 17 00:00:00 2001
|
|
From: Jon Maloy <jmaloy@redhat.com>
|
|
Date: Wed, 21 Apr 2021 22:30:03 -0400
|
|
Subject: [PATCH 4/7] memory: Revert "memory: accept mismatching sizes in
|
|
memory_region_access_valid"
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
|
Message-id: <20210421223006.19650-4-jmaloy@redhat.com>
|
|
Patchwork-id: 101480
|
|
O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 3/6] memory: Revert "memory: accept mismatching sizes in memory_region_access_valid"
|
|
Bugzilla: 1842478
|
|
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
|
From: "Michael S. Tsirkin" <mst@redhat.com>
|
|
|
|
Memory API documentation documents valid .min_access_size and .max_access_size
|
|
fields and explains that any access outside these boundaries is blocked.
|
|
|
|
This is what devices seem to assume.
|
|
|
|
However this is not what the implementation does: it simply
|
|
ignores the boundaries unless there's an "accepts" callback.
|
|
|
|
Naturally, this breaks a bunch of devices.
|
|
|
|
Revert to the documented behaviour.
|
|
|
|
Devices that want to allow any access can just drop the valid field,
|
|
or add the impl field to have accesses converted to appropriate
|
|
length.
|
|
|
|
Cc: qemu-stable@nongnu.org
|
|
Reviewed-by: Richard Henderson <rth@twiddle.net>
|
|
Fixes: CVE-2020-13754
|
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1842363
|
|
Fixes: a014ed07bd5a ("memory: accept mismatching sizes in memory_region_access_valid")
|
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Message-Id: <20200610134731.1514409-1-mst@redhat.com>
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
|
(cherry picked from commit 5d971f9e672507210e77d020d89e0e89165c8fc9)
|
|
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
|
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
---
|
|
memory.c | 29 +++++++++--------------------
|
|
1 file changed, 9 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/memory.c b/memory.c
|
|
index 5a4a80842d..0cfcb72a5a 100644
|
|
--- a/memory.c
|
|
+++ b/memory.c
|
|
@@ -1351,35 +1351,24 @@ bool memory_region_access_valid(MemoryRegion *mr,
|
|
bool is_write,
|
|
MemTxAttrs attrs)
|
|
{
|
|
- int access_size_min, access_size_max;
|
|
- int access_size, i;
|
|
-
|
|
- if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
|
|
+ if (mr->ops->valid.accepts
|
|
+ && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write, attrs)) {
|
|
return false;
|
|
}
|
|
|
|
- if (!mr->ops->valid.accepts) {
|
|
- return true;
|
|
- }
|
|
-
|
|
- access_size_min = mr->ops->valid.min_access_size;
|
|
- if (!mr->ops->valid.min_access_size) {
|
|
- access_size_min = 1;
|
|
+ if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
|
|
+ return false;
|
|
}
|
|
|
|
- access_size_max = mr->ops->valid.max_access_size;
|
|
+ /* Treat zero as compatibility all valid */
|
|
if (!mr->ops->valid.max_access_size) {
|
|
- access_size_max = 4;
|
|
+ return true;
|
|
}
|
|
|
|
- access_size = MAX(MIN(size, access_size_max), access_size_min);
|
|
- for (i = 0; i < size; i += access_size) {
|
|
- if (!mr->ops->valid.accepts(mr->opaque, addr + i, access_size,
|
|
- is_write, attrs)) {
|
|
- return false;
|
|
- }
|
|
+ if (size > mr->ops->valid.max_access_size
|
|
+ || size < mr->ops->valid.min_access_size) {
|
|
+ return false;
|
|
}
|
|
-
|
|
return true;
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|