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