dcavalca / rpms / qemu

Forked from rpms/qemu 11 months ago
Clone

Blame 0002-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch

18eddd
From: Petr Matousek <pmatouse@redhat.com>
18eddd
Date: Wed, 6 May 2015 09:48:59 +0200
18eddd
Subject: [PATCH] fdc: force the fifo access to be in bounds of the allocated
18eddd
 buffer
18eddd
18eddd
During processing of certain commands such as FD_CMD_READ_ID and
18eddd
FD_CMD_DRIVE_SPECIFICATION_COMMAND the fifo memory access could
18eddd
get out of bounds leading to memory corruption with values coming
18eddd
from the guest.
18eddd
18eddd
Fix this by making sure that the index is always bounded by the
18eddd
allocated memory.
18eddd
18eddd
This is CVE-2015-3456.
18eddd
18eddd
Signed-off-by: Petr Matousek <pmatouse@redhat.com>
18eddd
Reviewed-by: John Snow <jsnow@redhat.com>
18eddd
Signed-off-by: John Snow <jsnow@redhat.com>
18eddd
(cherry picked from commit e907746266721f305d67bc0718795fedee2e824c)
18eddd
---
18eddd
 hw/block/fdc.c | 17 +++++++++++------
18eddd
 1 file changed, 11 insertions(+), 6 deletions(-)
18eddd
18eddd
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
18eddd
index 2bf87c9..a9de4ab 100644
18eddd
--- a/hw/block/fdc.c
18eddd
+++ b/hw/block/fdc.c
18eddd
@@ -1512,7 +1512,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
18eddd
 {
18eddd
     FDrive *cur_drv;
18eddd
     uint32_t retval = 0;
18eddd
-    int pos;
18eddd
+    uint32_t pos;
18eddd
 
18eddd
     cur_drv = get_cur_drv(fdctrl);
18eddd
     fdctrl->dsr &= ~FD_DSR_PWRDOWN;
18eddd
@@ -1521,8 +1521,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
18eddd
         return 0;
18eddd
     }
18eddd
     pos = fdctrl->data_pos;
18eddd
+    pos %= FD_SECTOR_LEN;
18eddd
     if (fdctrl->msr & FD_MSR_NONDMA) {
18eddd
-        pos %= FD_SECTOR_LEN;
18eddd
         if (pos == 0) {
18eddd
             if (fdctrl->data_pos != 0)
18eddd
                 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
18eddd
@@ -1867,10 +1867,13 @@ static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
18eddd
 static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction)
18eddd
 {
18eddd
     FDrive *cur_drv = get_cur_drv(fdctrl);
18eddd
+    uint32_t pos;
18eddd
 
18eddd
-    if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
18eddd
+    pos = fdctrl->data_pos - 1;
18eddd
+    pos %= FD_SECTOR_LEN;
18eddd
+    if (fdctrl->fifo[pos] & 0x80) {
18eddd
         /* Command parameters done */
18eddd
-        if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
18eddd
+        if (fdctrl->fifo[pos] & 0x40) {
18eddd
             fdctrl->fifo[0] = fdctrl->fifo[1];
18eddd
             fdctrl->fifo[2] = 0;
18eddd
             fdctrl->fifo[3] = 0;
18eddd
@@ -1970,7 +1973,7 @@ static uint8_t command_to_handler[256];
18eddd
 static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
18eddd
 {
18eddd
     FDrive *cur_drv;
18eddd
-    int pos;
18eddd
+    uint32_t pos;
18eddd
 
18eddd
     /* Reset mode */
18eddd
     if (!(fdctrl->dor & FD_DOR_nRESET)) {
18eddd
@@ -2019,7 +2022,9 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
18eddd
     }
18eddd
 
18eddd
     FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
18eddd
-    fdctrl->fifo[fdctrl->data_pos++] = value;
18eddd
+    pos = fdctrl->data_pos++;
18eddd
+    pos %= FD_SECTOR_LEN;
18eddd
+    fdctrl->fifo[pos] = value;
18eddd
     if (fdctrl->data_pos == fdctrl->data_len) {
18eddd
         /* We now have all parameters
18eddd
          * and will be able to treat the command