Blame SOURCES/kvm-memory-Revert-memory-accept-mismatching-sizes-in-mem.patch

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