Bug 1665371 (CVE-2019-3813)
Summary: | CVE-2019-3813 spice: Off-by-one error in array access in spice/server/memslot.c | ||
---|---|---|---|
Product: | [Other] Security Response | Reporter: | Andrej Nemec <anemec> |
Component: | vulnerability | Assignee: | Red Hat Product Security <security-response-team> |
Status: | CLOSED ERRATA | QA Contact: | |
Severity: | high | Docs Contact: | |
Priority: | high | ||
Version: | unspecified | CC: | alon, bmcclain, cfergeau, cshao, dblechte, dfediuck, dmoppert, eedri, hdegoede, jforbes, kraxel, marcandre.lureau, mgoldboi, michal.skrivanek, mkenneth, rh-spice-bugs, sandmann, sbonazzo, security-response-team, sgayou, sherold, victortoso, yturgema |
Target Milestone: | --- | Keywords: | Security |
Target Release: | --- | ||
Hardware: | All | ||
OS: | Linux | ||
Whiteboard: | |||
Fixed In Version: | spice 0.14.2 | Doc Type: | If docs needed, set a value |
Doc Text: |
Spice, versions 0.5.2 through 0.14.1, are vulnerable to an out-of-bounds read due to an off-by-one error in memslot_get_virt. This may lead to a denial of service, or, in the worst case, code-execution by unauthenticated attackers.
|
Story Points: | --- |
Clone Of: | Environment: | ||
Last Closed: | 2019-01-31 20:08:31 UTC | Type: | --- |
Regression: | --- | Mount Type: | --- |
Documentation: | --- | CRM: | |
Verified Versions: | Category: | --- | |
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
Cloudforms Team: | --- | Target Upstream Version: | |
Embargoed: | |||
Bug Depends On: | 1666830, 1666831, 1669226, 1670158, 1670159, 1672153, 1672154 | ||
Bug Blocks: | 1663867 |
Description
Andrej Nemec
2019-01-11 07:35:53 UTC
Does look like it can change program control flow assuming checks can be bypassed, an attacker can control the heap information past the end of the buffer, etc. memslot_get_virt looks to return chunks of memory back to callers that are then cast into different structs and used. Thus, information leaks may be possible, lots of other super-undefined behavior could potentially occur (i.e. code execution) ``` │1426 qxl = (QXLCursor *)memslot_get_virt(slots, addr, sizeof(*qxl), group_id, &error); │ >│1427 if (error) { │ │1428 return false; │ │1429 } │ │1430 │ │1431 red->header.unique = qxl->header.unique; │ │1432 red->header.type = qxl->header.type; │ ``` another example of a use of memslot_get_virt: ``` │1463 bool red_get_cursor_cmd(RedMemSlotInfo *slots, int group_id, │ │1464 RedCursorCmd *red, QXLPHYSICAL addr) │ │1465 { │ │1466 QXLCursorCmd *qxl; │ │1467 int error; │ │1468 │ >│1469 qxl = (QXLCursorCmd *)memslot_get_virt(slots, addr, sizeof(*qxl), group_id, &error); │ │1470 if (error) { │ │1471 return false; │ │1472 } │ │1473 red->release_info_ext.info = &qxl->release_info; │ │1474 red->release_info_ext.group_id = group_id; ``` For an attacker to control the output memslot_get_virt, it looks like they need at least the following to occur: 1. Control group_id or the QXLPHYSICAL addr. Reporter indicated group_id may be unlikely, but QXLPHYSICAL might be possible. 2. If addr is controlled, set higher byte to slot_id such that "return addr >> info->memslot_id_shift" returns a number equal to info->num_memslots. 3. Control the heap such that the now out-of-bounds read of &info->mem_slots[group_id][slot_id] allows some control of the structure. Attacker would then potentially be able to modify the following struct: ```c typedef struct MemSlot { int generation; unsigned long virt_start_addr; unsigned long virt_end_addr; long address_delta; } MemSlot; ``` 4. slot->generation would need to be set to what memslot_get_generation returns, which I think is just more information encoded into the addr. 5. h_virt could then potentially be set to anything via: ``` h_virt += slot->address_delta; ``` 6. memslot_validate_virt would need to be bypassed. With full control of the heap, I believe that wouldn't pose a problem. See the following line: ```c if (virt < slot->virt_start_addr || (virt + add_size) > slot->virt_end_addr) { ``` After all of these hypotheticals, an attacker could then return a controlled void* memslot_validate_virt to callers, who would then start processing those chunks of memory leading to further decay. That's my argument for potential (not easy, but possible) code execution. Highly likely I missed something, let me know. :) Also looks like an attacker may be able to change the group_id via modifying the QXL guest driver. ```c void spiceqxl_display_monitors_config(qxl_screen_t *qxl) { spice_qxl_monitors_config_async(&qxl->display_sin, physical_address(qxl, qxl->monitors_config, 0), MEMSLOT_GROUP, 0); } ``` MEMSLOT_GROUP is hardcoded to 0. So I believe an attacker can control this? Untested. Original commit -- a70110c4e50aad99de7a844bb78eb868768e7841 on Sat Nov 21 22:42:38 2009 +0200 ```bash git tag --contains a70110c4e50aad99de7a844bb78eb868768e7841 | sort -V 0.5.2 0.5.3 0.6.0 0.6.1 0.6.2 0.6.3 0.6.4 0.7.0 0.7.1 0.7.2 0.7.3 0.8.0 0.8.1 0.8.2 0.8.3 0.9.0 0.9.1 0.10.0 0.10.1 0.11.0 0.11.3 0.12.0 v0.12.0 v0.12.2 v0.12.3 v0.12.4 v0.12.5 v0.12.6 v0.12.8 v0.13.0 v0.13.1 v0.13.2 v0.13.3 v0.13.90 v0.13.91 v0.14.0 v0.14.1 ``` Thus, RHEL6 (spice-server 12.4) also impacted via the get_virt function in red_memslots.c. (In reply to Scott Gayou from comment #6) > Also looks like an attacker may be able to change the group_id via modifying > the QXL guest driver. > > ```c > void spiceqxl_display_monitors_config(qxl_screen_t *qxl) > { > spice_qxl_monitors_config_async(&qxl->display_sin, physical_address(qxl, > qxl->monitors_config, 0), > MEMSLOT_GROUP, 0); > } > ``` > MEMSLOT_GROUP is hardcoded to 0. So I believe an attacker can control this? > Untested. spiceqxl_*.c is not part of the QXL driver which runs on the guest, it's a xorg driver which will directly link with spice-server, and will allow to export a xorg display over SPICE. I'm fairly confident group_id is never obtained from guest data, but is always hardcoded to a valid value by QEMU. Acknowledgments: Name: Christophe Fergeau (Red Hat) Created spice tracking bugs for this issue: Affects: fedora-all [bug 1670158] Unembargoed. This issue has been addressed in the following products: Red Hat Enterprise Linux 7 Via RHSA-2019:0231 https://access.redhat.com/errata/RHSA-2019:0231 This issue has been addressed in the following products: Red Hat Enterprise Linux 6 Via RHSA-2019:0232 https://access.redhat.com/errata/RHSA-2019:0232 Upstream Patch: https://gitlab.freedesktop.org/spice/spice/commit/a4a16ac42d2f19a17e36556546aa94d5cd83745f This issue has been addressed in the following products: Red Hat Virtualization 4 for Red Hat Enterprise Linux 7 Via RHSA-2019:0457 https://access.redhat.com/errata/RHSA-2019:0457 |