[spice-server v2 2/2] memslot: Fix off-by-one error in group/slot boundary check

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



RedMemSlotInfo keeps an array of groups, and each group contains an
array of slots. Unfortunately, these checks are off by 1, they check
that the index is greater or equal to the number of elements in the
array, while these arrays are 0 based. The check should only check for
strictly greater than the number of elements.

For the group array, this is not a big issue, as these memslot groups
are created by spice-server users (eg QEMU), and the group ids used to
index that array are also generated by the spice-server user, so it
should not be possible for the guest to set them to arbitrary values.

The slot id is more problematic, as it's calculated from a QXLPHYSICAL
address, and such addresses are usually set by the guest QXL driver, so
the guest can set these to arbitrary values, including malicious values,
which are probably easy to build from the guest PCI configuration.

This patch fixes the arrays bound check, and adds a test case for this.
This fixes CVE-2019-3813.

Signed-off-by: Christophe Fergeau <cfergeau@xxxxxxxxxx>
---
 server/memslot.c                |  4 ++--
 server/tests/test-qxl-parsing.c | 30 ++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/server/memslot.c b/server/memslot.c
index c29313214..97311b2e5 100644
--- a/server/memslot.c
+++ b/server/memslot.c
@@ -97,13 +97,13 @@ void *memslot_get_virt(RedMemSlotInfo *info, QXLPHYSICAL addr, uint32_t add_size
 
     MemSlot *slot;
 
-    if (group_id > info->num_memslots_groups) {
+    if (group_id >= info->num_memslots_groups) {
         spice_critical("group_id too big");
         return NULL;
     }
 
     slot_id = memslot_get_id(info, addr);
-    if (slot_id > info->num_memslots) {
+    if (slot_id >= info->num_memslots) {
         print_memslots(info);
         spice_critical("slot_id %d too big, addr=%" PRIx64, slot_id, addr);
         return NULL;
diff --git a/server/tests/test-qxl-parsing.c b/server/tests/test-qxl-parsing.c
index 324f7fdc9..edccfee47 100644
--- a/server/tests/test-qxl-parsing.c
+++ b/server/tests/test-qxl-parsing.c
@@ -85,6 +85,31 @@ static void deinit_qxl_surface(QXLSurfaceCmd *qxl)
     g_free(from_physical(qxl->u.surface_create.data));
 }
 
+static void test_memslot_invalid_group_id(void)
+{
+    RedMemSlotInfo mem_info;
+    init_meminfo(&mem_info);
+
+    memslot_get_virt(&mem_info, 0, 16, 1);
+}
+
+static void test_memslot_invalid_slot_id(void)
+{
+    RedMemSlotInfo mem_info;
+    init_meminfo(&mem_info);
+
+    memslot_get_virt(&mem_info, 1 << mem_info.memslot_id_shift, 16, 0);
+}
+
+static void test_memslot_invalid_addresses(void)
+{
+    g_test_trap_subprocess("/server/memslot-invalid-addresses/subprocess/group_id", 0, 0);
+    g_test_trap_assert_stderr("*group_id too big*");
+
+    g_test_trap_subprocess("/server/memslot-invalid-addresses/subprocess/slot_id", 0, 0);
+    g_test_trap_assert_stderr("*slot_id 1 too big*");
+}
+
 static void test_no_issues(void)
 {
     RedMemSlotInfo mem_info;
@@ -269,6 +294,11 @@ int main(int argc, char *argv[])
 {
     g_test_init(&argc, &argv, NULL);
 
+    /* try to use invalid memslot group/slot */
+    g_test_add_func("/server/memslot-invalid-addresses", test_memslot_invalid_addresses);
+    g_test_add_func("/server/memslot-invalid-addresses/subprocess/group_id", test_memslot_invalid_group_id);
+    g_test_add_func("/server/memslot-invalid-addresses/subprocess/slot_id", test_memslot_invalid_slot_id);
+
     /* try to create a surface with no issues, should succeed */
     g_test_add_func("/server/qxl-parsing-no-issues", test_no_issues);
 
-- 
2.20.1

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel




[Index of Archives]     [Linux Virtualization]     [Linux Virtualization]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]