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