Blame SOURCES/kvm-hw-block-fdc-Prevent-end-of-track-overrun-CVE-2021-3.patch

29b115
From 6ee4a8718dcce2d6da43ee200534b75baf1d7bbe Mon Sep 17 00:00:00 2001
29b115
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
29b115
Date: Thu, 18 Nov 2021 12:57:32 +0100
29b115
Subject: [PATCH 16/17] hw/block/fdc: Prevent end-of-track overrun
29b115
 (CVE-2021-3507)
29b115
MIME-Version: 1.0
29b115
Content-Type: text/plain; charset=UTF-8
29b115
Content-Transfer-Encoding: 8bit
29b115
29b115
RH-Author: Jon Maloy <jmaloy@redhat.com>
29b115
RH-MergeRequest: 107: hw/block/fdc: Prevent end-of-track overrun (CVE-2021-3507)
29b115
RH-Commit: [1/2] 9ffc5290348884d20b894fa79f4d0c8089247f8b (mrezanin/centos-src-qemu-kvm)
29b115
RH-Bugzilla: 1951522
29b115
RH-Acked-by: Hanna Reitz <hreitz@redhat.com>
29b115
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
29b115
29b115
Per the 82078 datasheet, if the end-of-track (EOT byte in
29b115
the FIFO) is more than the number of sectors per side, the
29b115
command is terminated unsuccessfully:
29b115
29b115
* 5.2.5 DATA TRANSFER TERMINATION
29b115
29b115
  The 82078 supports terminal count explicitly through
29b115
  the TC pin and implicitly through the underrun/over-
29b115
  run and end-of-track (EOT) functions. For full sector
29b115
  transfers, the EOT parameter can define the last
29b115
  sector to be transferred in a single or multisector
29b115
  transfer. If the last sector to be transferred is a par-
29b115
  tial sector, the host can stop transferring the data in
29b115
  mid-sector, and the 82078 will continue to complete
29b115
  the sector as if a hardware TC was received. The
29b115
  only difference between these implicit functions and
29b115
  TC is that they return "abnormal termination" result
29b115
  status. Such status indications can be ignored if they
29b115
  were expected.
29b115
29b115
* 6.1.3 READ TRACK
29b115
29b115
  This command terminates when the EOT specified
29b115
  number of sectors have been read. If the 82078
29b115
  does not find an I D Address Mark on the diskette
29b115
  after the second· occurrence of a pulse on the
29b115
  INDX# pin, then it sets the IC code in Status Regis-
29b115
  ter 0 to "01" (Abnormal termination), sets the MA bit
29b115
  in Status Register 1 to "1", and terminates the com-
29b115
  mand.
29b115
29b115
* 6.1.6 VERIFY
29b115
29b115
  Refer to Table 6-6 and Table 6-7 for information
29b115
  concerning the values of MT and EC versus SC and
29b115
  EOT value.
29b115
29b115
* Table 6·6. Result Phase Table
29b115
29b115
* Table 6-7. Verify Command Result Phase Table
29b115
29b115
Fix by aborting the transfer when EOT > # Sectors Per Side.
29b115
29b115
Cc: qemu-stable@nongnu.org
29b115
Cc: Hervé Poussineau <hpoussin@reactos.org>
29b115
Fixes: baca51faff0 ("floppy driver: disk geometry auto detect")
29b115
Reported-by: Alexander Bulekov <alxndr@bu.edu>
29b115
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/339
29b115
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
29b115
Message-Id: <20211118115733.4038610-2-philmd@redhat.com>
29b115
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
29b115
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
29b115
(cherry picked from commit defac5e2fbddf8423a354ff0454283a2115e1367)
29b115
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
29b115
---
29b115
 hw/block/fdc.c | 8 ++++++++
29b115
 1 file changed, 8 insertions(+)
29b115
29b115
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
29b115
index ca1776121f..6481ec0cfb 100644
29b115
--- a/hw/block/fdc.c
29b115
+++ b/hw/block/fdc.c
29b115
@@ -1532,6 +1532,14 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
29b115
         int tmp;
29b115
         fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
29b115
         tmp = (fdctrl->fifo[6] - ks + 1);
29b115
+        if (tmp < 0) {
29b115
+            FLOPPY_DPRINTF("invalid EOT: %d\n", tmp);
29b115
+            fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
29b115
+            fdctrl->fifo[3] = kt;
29b115
+            fdctrl->fifo[4] = kh;
29b115
+            fdctrl->fifo[5] = ks;
29b115
+            return;
29b115
+        }
29b115
         if (fdctrl->fifo[0] & 0x80)
29b115
             tmp += fdctrl->fifo[6];
29b115
         fdctrl->data_len *= tmp;
29b115
-- 
29b115
2.31.1
29b115