yeahuh / rpms / qemu-kvm

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