05bba0
From ef9148789f335927506b9f86fe6805b764d57d27 Mon Sep 17 00:00:00 2001
1200d7
From: Miroslav Rezanina <mrezanin@redhat.com>
05bba0
Date: Mon, 11 May 2015 10:13:23 +0200
05bba0
Subject: [PATCH 6/6] fdc: force the fifo access to be in bounds of the
05bba0
 allocated buffer
1200d7
05bba0
Message-id: <1431332003-30588-1-git-send-email-mrezanin@redhat.com>
05bba0
O-Subject: [RHEL-7.2 qemu-kvm EMBARGOED PATCH] fdc: force the fifo access
05bba0
           to be in bounds of the allocated buffer
05bba0
Bugzilla: 1219270
05bba0
RH-Acked-by: Reviewed-by: Markus Armbruster <armbru@redhat.com>
05bba0
RH-Acked-by: Reviewed-by: Kevin Wolf <kwolf@redhat.com>
05bba0
RH-Acked-by: Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
1200d7
1200d7
During processing of certain commands such as FD_CMD_READ_ID and
1200d7
FD_CMD_DRIVE_SPECIFICATION_COMMAND the fifo memory access could
1200d7
get out of bounds leading to memory corruption with values coming
1200d7
from the guest.
1200d7
1200d7
Fix this by making sure that the index is always bounded by the
1200d7
allocated memory.
1200d7
1200d7
This is CVE-2015-3456.
1200d7
05bba0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
1200d7
---
1200d7
 hw/block/fdc.c | 17 +++++++++++------
1200d7
 1 file changed, 11 insertions(+), 6 deletions(-)
1200d7
1200d7
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
1200d7
index 322d863..56aedcc 100644
1200d7
--- a/hw/block/fdc.c
1200d7
+++ b/hw/block/fdc.c
1200d7
@@ -1434,7 +1434,7 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
1200d7
 {
1200d7
     FDrive *cur_drv;
1200d7
     uint32_t retval = 0;
1200d7
-    int pos;
1200d7
+    uint32_t pos;
1200d7
 
1200d7
     cur_drv = get_cur_drv(fdctrl);
1200d7
     fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1200d7
@@ -1443,8 +1443,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
1200d7
         return 0;
1200d7
     }
1200d7
     pos = fdctrl->data_pos;
1200d7
+    pos %= FD_SECTOR_LEN;
1200d7
     if (fdctrl->msr & FD_MSR_NONDMA) {
1200d7
-        pos %= FD_SECTOR_LEN;
1200d7
         if (pos == 0) {
1200d7
             if (fdctrl->data_pos != 0)
1200d7
                 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
1200d7
@@ -1788,10 +1788,13 @@ static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
1200d7
 static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction)
1200d7
 {
1200d7
     FDrive *cur_drv = get_cur_drv(fdctrl);
1200d7
+    uint32_t pos;
1200d7
 
1200d7
-    if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
1200d7
+    pos = fdctrl->data_pos - 1;
1200d7
+    pos %= FD_SECTOR_LEN;
1200d7
+    if (fdctrl->fifo[pos] & 0x80) {
1200d7
         /* Command parameters done */
1200d7
-        if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
1200d7
+        if (fdctrl->fifo[pos] & 0x40) {
1200d7
             fdctrl->fifo[0] = fdctrl->fifo[1];
1200d7
             fdctrl->fifo[2] = 0;
1200d7
             fdctrl->fifo[3] = 0;
1200d7
@@ -1891,7 +1894,7 @@ static uint8_t command_to_handler[256];
1200d7
 static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
1200d7
 {
1200d7
     FDrive *cur_drv;
1200d7
-    int pos;
1200d7
+    uint32_t pos;
1200d7
 
1200d7
     /* Reset mode */
1200d7
     if (!(fdctrl->dor & FD_DOR_nRESET)) {
1200d7
@@ -1939,7 +1942,9 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
1200d7
     }
1200d7
 
1200d7
     FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
1200d7
-    fdctrl->fifo[fdctrl->data_pos++] = value;
1200d7
+    pos = fdctrl->data_pos++;
1200d7
+    pos %= FD_SECTOR_LEN;
1200d7
+    fdctrl->fifo[pos] = value;
1200d7
     if (fdctrl->data_pos == fdctrl->data_len) {
1200d7
         /* We now have all parameters
1200d7
          * and will be able to treat the command
1200d7
-- 
1200d7
1.8.3.1
1200d7