diff --git a/0018-hw-scsi-lsi53c895a-Do-not-abort-when-DMA-requested.patch b/0018-hw-scsi-lsi53c895a-Do-not-abort-when-DMA-requested.patch new file mode 100644 index 0000000..c1cf822 --- /dev/null +++ b/0018-hw-scsi-lsi53c895a-Do-not-abort-when-DMA-requested.patch @@ -0,0 +1,68 @@ +From 9c499bfc3c1e028cc35242d66a44efd536496480 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 23 Nov 2021 12:17:31 +0100 +Subject: [PATCH] hw/scsi/lsi53c895a: Do not abort when DMA requested and no + data queued +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If asked for DMA request and no data is available, simply wait +for data to be queued, do not abort. This fixes: + + $ cat << EOF | \ + qemu-system-i386 -nographic -M q35,accel=qtest -serial none \ + -monitor none -qtest stdio -trace lsi* \ + -drive if=none,id=drive0,file=null-co://,file.read-zeroes=on,format=raw \ + -device lsi53c895a,id=scsi0 -device scsi-hd,drive=drive0,bus=scsi0.0,channel=0,scsi-id=0,lun=0 + lsi_reset Reset + lsi_reg_write Write reg DSP2 0x2e = 0xff + lsi_reg_write Write reg DSP3 0x2f = 0xff + lsi_execute_script SCRIPTS dsp=0xffff0000 opcode 0x184a3900 arg 0x4a8b2d75 + qemu-system-i386: hw/scsi/lsi53c895a.c:624: lsi_do_dma: Assertion `s->current' failed. + + (gdb) bt + #5 0x00007ffff4e8a3a6 in __GI___assert_fail + (assertion=0x5555560accbc "s->current", file=0x5555560acc28 "hw/scsi/lsi53c895a.c", line=624, function=0x5555560adb18 "lsi_do_dma") at assert.c:101 + #6 0x0000555555aa33b9 in lsi_do_dma (s=0x555557805ac0, out=1) at hw/scsi/lsi53c895a.c:624 + #7 0x0000555555aa5042 in lsi_execute_script (s=0x555557805ac0) at hw/scsi/lsi53c895a.c:1250 + #8 0x0000555555aa757a in lsi_reg_writeb (s=0x555557805ac0, offset=47, val=255 '\377') at hw/scsi/lsi53c895a.c:1984 + #9 0x0000555555aa875b in lsi_mmio_write (opaque=0x555557805ac0, addr=47, val=255, size=1) at hw/scsi/lsi53c895a.c:2095 + +Cc: qemu-stable@nongnu.org +Cc: Gerd Hoffmann +Cc: Vadim Rozenfeld +Cc: Stefan Hajnoczi +Reported-by: Jérôme Poulin +Reported-by: Ruhr-University +Reported-by: Gaoning Pan +Reported-by: Cheolwoo Myung +Fixes: b96a0da06bd ("lsi: move dma_len+dma_buf into lsi_request") +BugLink: https://bugs.launchpad.net/qemu/+bug/697510 +BugLink: https://bugs.launchpad.net/qemu/+bug/1905521 +BugLink: https://bugs.launchpad.net/qemu/+bug/1908515 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/84 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/305 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/552 +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Laurent Vivier +Message-Id: <20211123111732.83137-2-philmd@redhat.com> +Signed-off-by: Paolo Bonzini +--- + hw/scsi/lsi53c895a.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index 85e907a785..4c431adb77 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -621,8 +621,7 @@ static void lsi_do_dma(LSIState *s, int out) + dma_addr_t addr; + SCSIDevice *dev; + +- assert(s->current); +- if (!s->current->dma_len) { ++ if (!s->current || !s->current->dma_len) { + /* Wait until data is available. */ + trace_lsi_do_dma_unavailable(); + return; diff --git a/0019-tests-qtest-Add-fuzz-lsi53c895a-test.patch b/0019-tests-qtest-Add-fuzz-lsi53c895a-test.patch new file mode 100644 index 0000000..368207f --- /dev/null +++ b/0019-tests-qtest-Add-fuzz-lsi53c895a-test.patch @@ -0,0 +1,110 @@ +From 610522d33e6b4820ed1e3a93bff135afaad17664 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 23 Nov 2021 12:17:32 +0100 +Subject: [PATCH] tests/qtest: Add fuzz-lsi53c895a-test +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Without the previous commit, this test triggers: + + $ make check-qtest-x86_64 + [...] + Running test qtest-x86_64/fuzz-lsi53c895a-test + qemu-system-x86_64: hw/scsi/lsi53c895a.c:624: lsi_do_dma: Assertion `s->current' failed. + ERROR qtest-x86_64/fuzz-lsi53c895a-test - too few tests run (expected 1, got 0) + +Suggested-by: Alexander Bulekov +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Laurent Vivier +Message-Id: <20211123111732.83137-3-philmd@redhat.com> +Signed-off-by: Paolo Bonzini +--- + MAINTAINERS | 1 + + tests/qtest/fuzz-lsi53c895a-test.c | 52 ++++++++++++++++++++++++++++++ + tests/qtest/meson.build | 1 + + 3 files changed, 54 insertions(+) + create mode 100644 tests/qtest/fuzz-lsi53c895a-test.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index 7543eb4d59..fbd6d0b174 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1825,6 +1825,7 @@ F: hw/scsi/* + F: tests/qtest/virtio-scsi-test.c + F: tests/qtest/fuzz-virtio-scsi-test.c + F: tests/qtest/am53c974-test.c ++F: tests/qtest/fuzz-lsi53c895a-test.c + T: git https://github.com/bonzini/qemu.git scsi-next + + SSI +diff --git a/tests/qtest/fuzz-lsi53c895a-test.c b/tests/qtest/fuzz-lsi53c895a-test.c +new file mode 100644 +index 0000000000..ba5d468970 +--- /dev/null ++++ b/tests/qtest/fuzz-lsi53c895a-test.c +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * QTest fuzzer-generated testcase for LSI53C895A device ++ * ++ * Copyright (c) Red Hat ++ */ ++ ++#include "qemu/osdep.h" ++#include "libqos/libqtest.h" ++ ++/* ++ * This used to trigger the assert in lsi_do_dma() ++ * https://bugs.launchpad.net/qemu/+bug/697510 ++ * https://bugs.launchpad.net/qemu/+bug/1905521 ++ * https://bugs.launchpad.net/qemu/+bug/1908515 ++ */ ++static void test_lsi_do_dma_empty_queue(void) ++{ ++ QTestState *s; ++ ++ s = qtest_init("-M q35 -nographic -monitor none -serial none " ++ "-drive if=none,id=drive0," ++ "file=null-co://,file.read-zeroes=on,format=raw " ++ "-device lsi53c895a,id=scsi0 " ++ "-device scsi-hd,drive=drive0," ++ "bus=scsi0.0,channel=0,scsi-id=0,lun=0"); ++ qtest_outl(s, 0xcf8, 0x80001814); ++ qtest_outl(s, 0xcfc, 0xe1068000); ++ qtest_outl(s, 0xcf8, 0x80001818); ++ qtest_outl(s, 0xcf8, 0x80001804); ++ qtest_outw(s, 0xcfc, 0x7); ++ qtest_outl(s, 0xcf8, 0x80002010); ++ ++ qtest_writeb(s, 0xe106802e, 0xff); /* Fill DSP bits 16-23 */ ++ qtest_writeb(s, 0xe106802f, 0xff); /* Fill DSP bits 24-31: trigger SCRIPT */ ++ ++ qtest_quit(s); ++} ++ ++int main(int argc, char **argv) ++{ ++ const char *arch = qtest_get_arch(); ++ ++ g_test_init(&argc, &argv, NULL); ++ ++ if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { ++ qtest_add_func("fuzz/lsi53c895a/lsi_do_dma_empty_queue", ++ test_lsi_do_dma_empty_queue); ++ } ++ ++ return g_test_run(); ++} +diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build +index c9d8458062..d2ce20d304 100644 +--- a/tests/qtest/meson.build ++++ b/tests/qtest/meson.build +@@ -19,6 +19,7 @@ slow_qtests = { + + qtests_generic = \ + (config_all_devices.has_key('CONFIG_MEGASAS_SCSI_PCI') ? ['fuzz-megasas-test'] : []) + \ ++ (config_all_devices.has_key('CONFIG_LSI_SCSI_PCI') ? ['fuzz-lsi53c895a-test'] : []) + \ + (config_all_devices.has_key('CONFIG_VIRTIO_SCSI') ? ['fuzz-virtio-scsi-test'] : []) + \ + (config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) + \ + (config_all_devices.has_key('CONFIG_SDHCI_PCI') ? ['fuzz-sdcard-test'] : []) + \ diff --git a/0020-scsi-lsi53c895a-really-fix-use-after-free-in-lsi.patch b/0020-scsi-lsi53c895a-really-fix-use-after-free-in-lsi.patch new file mode 100644 index 0000000..370555d --- /dev/null +++ b/0020-scsi-lsi53c895a-really-fix-use-after-free-in-lsi.patch @@ -0,0 +1,140 @@ +From 9d7a14d1e93897842787ddba4a2a0b958299a781 Mon Sep 17 00:00:00 2001 +From: Mauro Matteo Cascella +Date: Mon, 11 Jul 2022 14:33:16 +0200 +Subject: [PATCH] scsi/lsi53c895a: really fix use-after-free in lsi_do_msgout + (CVE-2022-0216) + +Set current_req to NULL, not current_req->req, to prevent reusing a free'd +buffer in case of repeated SCSI cancel requests. Also apply the fix to +CLEAR QUEUE and BUS DEVICE RESET messages as well, since they also cancel +the request. + +Thanks to Alexander Bulekov for providing a reproducer. + +Fixes: CVE-2022-0216 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/972 +Signed-off-by: Mauro Matteo Cascella +Tested-by: Alexander Bulekov +Message-Id: <20220711123316.421279-1-mcascell@redhat.com> +Signed-off-by: Paolo Bonzini +--- + hw/scsi/lsi53c895a.c | 4 +- + tests/qtest/fuzz-lsi53c895a-test.c | 75 ++++++++++++++++++++++++++++++ + 2 files changed, 78 insertions(+), 1 deletion(-) + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index 4c431adb77..b9c9eb0dac 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -1028,8 +1028,9 @@ static void lsi_do_msgout(LSIState *s) + case 0x0d: + /* The ABORT TAG message clears the current I/O process only. */ + trace_lsi_do_msgout_abort(current_tag); +- if (current_req) { ++ if (current_req && current_req->req) { + scsi_req_cancel(current_req->req); ++ current_req = NULL; + } + lsi_disconnect(s); + break; +@@ -1055,6 +1056,7 @@ static void lsi_do_msgout(LSIState *s) + /* clear the current I/O process */ + if (s->current) { + scsi_req_cancel(s->current->req); ++ current_req = NULL; + } + + /* As the current implemented devices scsi_disk and scsi_generic +diff --git a/tests/qtest/fuzz-lsi53c895a-test.c b/tests/qtest/fuzz-lsi53c895a-test.c +index ba5d468970..0f968024c8 100644 +--- a/tests/qtest/fuzz-lsi53c895a-test.c ++++ b/tests/qtest/fuzz-lsi53c895a-test.c +@@ -8,6 +8,79 @@ + #include "qemu/osdep.h" + #include "libqos/libqtest.h" + ++/* ++ * This used to trigger a UAF in lsi_do_msgout() ++ * https://gitlab.com/qemu-project/qemu/-/issues/972 ++ */ ++static void test_lsi_do_msgout_cancel_req(void) ++{ ++ QTestState *s; ++ ++ if (sizeof(void *) == 4) { ++ g_test_skip("memory size too big for 32-bit build"); ++ return; ++ } ++ ++ s = qtest_init("-M q35 -m 4G -display none -nodefaults " ++ "-device lsi53c895a,id=scsi " ++ "-device scsi-hd,drive=disk0 " ++ "-drive file=null-co://,id=disk0,if=none,format=raw"); ++ ++ qtest_outl(s, 0xcf8, 0x80000810); ++ qtest_outl(s, 0xcf8, 0xc000); ++ qtest_outl(s, 0xcf8, 0x80000810); ++ qtest_outw(s, 0xcfc, 0x7); ++ qtest_outl(s, 0xcf8, 0x80000810); ++ qtest_outl(s, 0xcfc, 0xc000); ++ qtest_outl(s, 0xcf8, 0x80000804); ++ qtest_outw(s, 0xcfc, 0x05); ++ qtest_writeb(s, 0x69736c10, 0x08); ++ qtest_writeb(s, 0x69736c13, 0x58); ++ qtest_writeb(s, 0x69736c1a, 0x01); ++ qtest_writeb(s, 0x69736c1b, 0x06); ++ qtest_writeb(s, 0x69736c22, 0x01); ++ qtest_writeb(s, 0x69736c23, 0x07); ++ qtest_writeb(s, 0x69736c2b, 0x02); ++ qtest_writeb(s, 0x69736c48, 0x08); ++ qtest_writeb(s, 0x69736c4b, 0x58); ++ qtest_writeb(s, 0x69736c52, 0x04); ++ qtest_writeb(s, 0x69736c53, 0x06); ++ qtest_writeb(s, 0x69736c5b, 0x02); ++ qtest_outl(s, 0xc02d, 0x697300); ++ qtest_writeb(s, 0x5a554662, 0x01); ++ qtest_writeb(s, 0x5a554663, 0x07); ++ qtest_writeb(s, 0x5a55466a, 0x10); ++ qtest_writeb(s, 0x5a55466b, 0x22); ++ qtest_writeb(s, 0x5a55466c, 0x5a); ++ qtest_writeb(s, 0x5a55466d, 0x5a); ++ qtest_writeb(s, 0x5a55466e, 0x34); ++ qtest_writeb(s, 0x5a55466f, 0x5a); ++ qtest_writeb(s, 0x5a345a5a, 0x77); ++ qtest_writeb(s, 0x5a345a5b, 0x55); ++ qtest_writeb(s, 0x5a345a5c, 0x51); ++ qtest_writeb(s, 0x5a345a5d, 0x27); ++ qtest_writeb(s, 0x27515577, 0x41); ++ qtest_outl(s, 0xc02d, 0x5a5500); ++ qtest_writeb(s, 0x364001d0, 0x08); ++ qtest_writeb(s, 0x364001d3, 0x58); ++ qtest_writeb(s, 0x364001da, 0x01); ++ qtest_writeb(s, 0x364001db, 0x26); ++ qtest_writeb(s, 0x364001dc, 0x0d); ++ qtest_writeb(s, 0x364001dd, 0xae); ++ qtest_writeb(s, 0x364001de, 0x41); ++ qtest_writeb(s, 0x364001df, 0x5a); ++ qtest_writeb(s, 0x5a41ae0d, 0xf8); ++ qtest_writeb(s, 0x5a41ae0e, 0x36); ++ qtest_writeb(s, 0x5a41ae0f, 0xd7); ++ qtest_writeb(s, 0x5a41ae10, 0x36); ++ qtest_writeb(s, 0x36d736f8, 0x0c); ++ qtest_writeb(s, 0x36d736f9, 0x80); ++ qtest_writeb(s, 0x36d736fa, 0x0d); ++ qtest_outl(s, 0xc02d, 0x364000); ++ ++ qtest_quit(s); ++} ++ + /* + * This used to trigger the assert in lsi_do_dma() + * https://bugs.launchpad.net/qemu/+bug/697510 +@@ -46,6 +119,8 @@ int main(int argc, char **argv) + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qtest_add_func("fuzz/lsi53c895a/lsi_do_dma_empty_queue", + test_lsi_do_dma_empty_queue); ++ qtest_add_func("fuzz/lsi53c895a/lsi_do_msgout_cancel_req", ++ test_lsi_do_msgout_cancel_req); + } + + return g_test_run(); diff --git a/qemu.spec b/qemu.spec index 7d469ab..66ea34b 100644 --- a/qemu.spec +++ b/qemu.spec @@ -306,7 +306,7 @@ Obsoletes: %{name}-system-unicore32-core <= %{epoch}:%{version}-%{release} %endif # To prevent rpmdev-bumpspec breakage -%global baserelease 13 +%global baserelease 14 Summary: QEMU is a FAST! processor emulator Name: qemu @@ -359,9 +359,18 @@ Patch0015: 0015-hw-i386-amd_iommu-Fix-maybe-uninitialized-error-with.patch Patch0016: 0016-Update-bios-table-test-blobs-after-bugfix-backports.patch # vga: avoid crash if no default vga card -# https://gitlab.com/qemu-project/qemu/-/issues/978 +# https://bugzilla.redhat.com/show_bug.cgi?id=2095639 Patch0017: 0017-vga-avoid-crash-if-no-default-vga-card.patch +# lsi53c895a: Do not abort when DMA requested and no data queued +# https://gitlab.com/qemu-project/qemu/-/issues/552 +Patch0018: 0018-hw-scsi-lsi53c895a-Do-not-abort-when-DMA-requested.patch +Patch0019: 0019-tests-qtest-Add-fuzz-lsi53c895a-test.patch + +# lsi53c895a: Fix use-after-free in lsi_do_msgout (CVE-2022-0216) +# https://bugzilla.redhat.com/show_bug.cgi?id=2070902 +Patch0020: 0020-scsi-lsi53c895a-really-fix-use-after-free-in-lsi.patch + BuildRequires: meson >= %{meson_version} BuildRequires: zlib-devel BuildRequires: glib2-devel @@ -2689,9 +2698,12 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog +* Fri Aug 12 2022 Mauro Matteo Cascella - 2:6.2.0-14 +- lsi53c895a: Do not abort when DMA requested and no data queued (#552) +- lsi53c895a: Fix use-after-free in lsi_do_msgout (CVE-2022-0216) (rhbz#2070902) + * Fri Aug 5 2022 Mauro Matteo Cascella - 2:6.2.0-13 -- vga: avoid crash if no default vga card -- Resolves: https://gitlab.com/qemu-project/qemu/-/issues/978 +- vga: avoid crash if no default vga card (rhbz#2095639) * Sat Jun 11 2022 Cole Robinson - 2:6.2.0-12 - Adjust for Xen dropping 32bit arches