Blame SOURCES/0028-memslot-Fix-off-by-one-error-in-group-slot-boundary-.patch

063737
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
063737
From: Christophe Fergeau <cfergeau@redhat.com>
063737
Date: Thu, 29 Nov 2018 14:18:39 +0100
063737
Subject: [PATCH] memslot: Fix off-by-one error in group/slot boundary check
063737
063737
RedMemSlotInfo keeps an array of groups, and each group contains an
063737
array of slots. Unfortunately, these checks are off by 1, they check
063737
that the index is greater or equal to the number of elements in the
063737
array, while these arrays are 0 based. The check should only check for
063737
strictly greater than the number of elements.
063737
063737
For the group array, this is not a big issue, as these memslot groups
063737
are created by spice-server users (eg QEMU), and the group ids used to
063737
index that array are also generated by the spice-server user, so it
063737
should not be possible for the guest to set them to arbitrary values.
063737
063737
The slot id is more problematic, as it's calculated from a QXLPHYSICAL
063737
address, and such addresses are usually set by the guest QXL driver, so
063737
the guest can set these to arbitrary values, including malicious values,
063737
which are probably easy to build from the guest PCI configuration.
063737
063737
This patch fixes the arrays bound check, and adds a test case for this.
063737
063737
Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
063737
---
063737
 server/memslot.c                |  4 ++--
063737
 server/tests/test-qxl-parsing.c | 32 ++++++++++++++++++++++++++++++++
063737
 2 files changed, 34 insertions(+), 2 deletions(-)
063737
063737
diff --git a/server/memslot.c b/server/memslot.c
063737
index 7074b43..8c59c38 100644
063737
--- a/server/memslot.c
063737
+++ b/server/memslot.c
063737
@@ -99,14 +99,14 @@ unsigned long memslot_get_virt(RedMemSlotInfo *info, QXLPHYSICAL addr, uint32_t
063737
     MemSlot *slot;
063737
 
063737
     *error = 0;
063737
-    if (group_id > info->num_memslots_groups) {
063737
+    if (group_id >= info->num_memslots_groups) {
063737
         spice_critical("group_id too big");
063737
         *error = 1;
063737
         return 0;
063737
     }
063737
 
063737
     slot_id = memslot_get_id(info, addr);
063737
-    if (slot_id > info->num_memslots) {
063737
+    if (slot_id >= info->num_memslots) {
063737
         print_memslots(info);
063737
         spice_critical("slot_id %d too big, addr=%" PRIx64, slot_id, addr);
063737
         *error = 1;
063737
diff --git a/server/tests/test-qxl-parsing.c b/server/tests/test-qxl-parsing.c
063737
index 9c0c3b1..83f2083 100644
063737
--- a/server/tests/test-qxl-parsing.c
063737
+++ b/server/tests/test-qxl-parsing.c
063737
@@ -85,6 +85,33 @@ static void deinit_qxl_surface(QXLSurfaceCmd *qxl)
063737
     free(from_physical(qxl->u.surface_create.data));
063737
 }
063737
 
063737
+static void test_memslot_invalid_group_id(void)
063737
+{
063737
+    RedMemSlotInfo mem_info;
063737
+    int error;
063737
+    init_meminfo(&mem_info);
063737
+
063737
+    memslot_get_virt(&mem_info, 0, 16, 1, &error);
063737
+}
063737
+
063737
+static void test_memslot_invalid_slot_id(void)
063737
+{
063737
+    RedMemSlotInfo mem_info;
063737
+    int error;
063737
+    init_meminfo(&mem_info);
063737
+
063737
+    memslot_get_virt(&mem_info, 1 << mem_info.memslot_id_shift, 16, 0, &error);
063737
+}
063737
+
063737
+static void test_memslot_invalid_addresses(void)
063737
+{
063737
+    g_test_trap_subprocess("/server/memslot-invalid-addresses/subprocess/group_id", 0, 0);
063737
+    g_test_trap_assert_stderr("*group_id too big*");
063737
+
063737
+    g_test_trap_subprocess("/server/memslot-invalid-addresses/subprocess/slot_id", 0, 0);
063737
+    g_test_trap_assert_stderr("*slot_id 1 too big*");
063737
+}
063737
+
063737
 static void test_no_issues(void)
063737
 {
063737
     RedMemSlotInfo mem_info;
063737
@@ -262,6 +289,11 @@ int main(int argc, char *argv[])
063737
 {
063737
     g_test_init(&argc, &argv, NULL);
063737
 
063737
+    /* try to use invalid memslot group/slot */
063737
+    g_test_add_func("/server/memslot-invalid-addresses", test_memslot_invalid_addresses);
063737
+    g_test_add_func("/server/memslot-invalid-addresses/subprocess/group_id", test_memslot_invalid_group_id);
063737
+    g_test_add_func("/server/memslot-invalid-addresses/subprocess/slot_id", test_memslot_invalid_slot_id);
063737
+
063737
     /* try to create a surface with no issues, should succeed */
063737
     g_test_add_func("/server/qxl-parsing-no-issues", test_no_issues);
063737