blob: f332154b6a956bf5feffc79184f26d8ffbf6387e [file] [log] [blame]
Patrick Williams92b42cb2022-09-03 06:53:57 -05001From 5451bf6db85ce3da1238e9154d051ebccec8f171 Mon Sep 17 00:00:00 2001
2From: Mauro Matteo Cascella <mcascell@redhat.com>
3Date: Mon, 11 Jul 2022 14:33:16 +0200
4Subject: [PATCH 2/2] scsi/lsi53c895a: really fix use-after-free in
5 lsi_do_msgout (CVE-2022-0216)
6
7Set current_req to NULL, not current_req->req, to prevent reusing a free'd
8buffer in case of repeated SCSI cancel requests. Also apply the fix to
9CLEAR QUEUE and BUS DEVICE RESET messages as well, since they also cancel
10the request.
11
12Thanks to Alexander Bulekov for providing a reproducer.
13
14Fixes: CVE-2022-0216
15Resolves: https://gitlab.com/qemu-project/qemu/-/issues/972
16Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
17Tested-by: Alexander Bulekov <alxndr@bu.edu>
18Message-Id: <20220711123316.421279-1-mcascell@redhat.com>
19Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
20
21Upstream-Status: Backport [4367a20cc442c56b05611b4224de9a61908f9eac]
22CVE: CVE-2022-0216
23
24Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
25---
26 hw/scsi/lsi53c895a.c | 3 +-
27 tests/qtest/fuzz-lsi53c895a-test.c | 76 ++++++++++++++++++++++++++++++
28 2 files changed, 78 insertions(+), 1 deletion(-)
29
30diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
31index 99ea42d49..ad5f5e5f3 100644
32--- a/hw/scsi/lsi53c895a.c
33+++ b/hw/scsi/lsi53c895a.c
34@@ -1030,7 +1030,7 @@ static void lsi_do_msgout(LSIState *s)
35 trace_lsi_do_msgout_abort(current_tag);
36 if (current_req && current_req->req) {
37 scsi_req_cancel(current_req->req);
38- current_req->req = NULL;
39+ current_req = NULL;
40 }
41 lsi_disconnect(s);
42 break;
43@@ -1056,6 +1056,7 @@ static void lsi_do_msgout(LSIState *s)
44 /* clear the current I/O process */
45 if (s->current) {
46 scsi_req_cancel(s->current->req);
47+ current_req = NULL;
48 }
49
50 /* As the current implemented devices scsi_disk and scsi_generic
51diff --git a/tests/qtest/fuzz-lsi53c895a-test.c b/tests/qtest/fuzz-lsi53c895a-test.c
52index ba5d46897..c1af0ab1c 100644
53--- a/tests/qtest/fuzz-lsi53c895a-test.c
54+++ b/tests/qtest/fuzz-lsi53c895a-test.c
55@@ -8,6 +8,79 @@
56 #include "qemu/osdep.h"
57 #include "libqos/libqtest.h"
58
59+/*
60+ * This used to trigger a UAF in lsi_do_msgout()
61+ * https://gitlab.com/qemu-project/qemu/-/issues/972
62+ */
63+static void test_lsi_do_msgout_cancel_req(void)
64+{
65+ QTestState *s;
66+
67+ if (sizeof(void *) == 4) {
68+ g_test_skip("memory size too big for 32-bit build");
69+ return;
70+ }
71+
72+ s = qtest_init("-M q35 -m 4G -display none -nodefaults "
73+ "-device lsi53c895a,id=scsi "
74+ "-device scsi-hd,drive=disk0 "
75+ "-drive file=null-co://,id=disk0,if=none,format=raw");
76+
77+ qtest_outl(s, 0xcf8, 0x80000810);
78+ qtest_outl(s, 0xcf8, 0xc000);
79+ qtest_outl(s, 0xcf8, 0x80000810);
80+ qtest_outw(s, 0xcfc, 0x7);
81+ qtest_outl(s, 0xcf8, 0x80000810);
82+ qtest_outl(s, 0xcfc, 0xc000);
83+ qtest_outl(s, 0xcf8, 0x80000804);
84+ qtest_outw(s, 0xcfc, 0x05);
85+ qtest_writeb(s, 0x69736c10, 0x08);
86+ qtest_writeb(s, 0x69736c13, 0x58);
87+ qtest_writeb(s, 0x69736c1a, 0x01);
88+ qtest_writeb(s, 0x69736c1b, 0x06);
89+ qtest_writeb(s, 0x69736c22, 0x01);
90+ qtest_writeb(s, 0x69736c23, 0x07);
91+ qtest_writeb(s, 0x69736c2b, 0x02);
92+ qtest_writeb(s, 0x69736c48, 0x08);
93+ qtest_writeb(s, 0x69736c4b, 0x58);
94+ qtest_writeb(s, 0x69736c52, 0x04);
95+ qtest_writeb(s, 0x69736c53, 0x06);
96+ qtest_writeb(s, 0x69736c5b, 0x02);
97+ qtest_outl(s, 0xc02d, 0x697300);
98+ qtest_writeb(s, 0x5a554662, 0x01);
99+ qtest_writeb(s, 0x5a554663, 0x07);
100+ qtest_writeb(s, 0x5a55466a, 0x10);
101+ qtest_writeb(s, 0x5a55466b, 0x22);
102+ qtest_writeb(s, 0x5a55466c, 0x5a);
103+ qtest_writeb(s, 0x5a55466d, 0x5a);
104+ qtest_writeb(s, 0x5a55466e, 0x34);
105+ qtest_writeb(s, 0x5a55466f, 0x5a);
106+ qtest_writeb(s, 0x5a345a5a, 0x77);
107+ qtest_writeb(s, 0x5a345a5b, 0x55);
108+ qtest_writeb(s, 0x5a345a5c, 0x51);
109+ qtest_writeb(s, 0x5a345a5d, 0x27);
110+ qtest_writeb(s, 0x27515577, 0x41);
111+ qtest_outl(s, 0xc02d, 0x5a5500);
112+ qtest_writeb(s, 0x364001d0, 0x08);
113+ qtest_writeb(s, 0x364001d3, 0x58);
114+ qtest_writeb(s, 0x364001da, 0x01);
115+ qtest_writeb(s, 0x364001db, 0x26);
116+ qtest_writeb(s, 0x364001dc, 0x0d);
117+ qtest_writeb(s, 0x364001dd, 0xae);
118+ qtest_writeb(s, 0x364001de, 0x41);
119+ qtest_writeb(s, 0x364001df, 0x5a);
120+ qtest_writeb(s, 0x5a41ae0d, 0xf8);
121+ qtest_writeb(s, 0x5a41ae0e, 0x36);
122+ qtest_writeb(s, 0x5a41ae0f, 0xd7);
123+ qtest_writeb(s, 0x5a41ae10, 0x36);
124+ qtest_writeb(s, 0x36d736f8, 0x0c);
125+ qtest_writeb(s, 0x36d736f9, 0x80);
126+ qtest_writeb(s, 0x36d736fa, 0x0d);
127+ qtest_outl(s, 0xc02d, 0x364000);
128+
129+ qtest_quit(s);
130+}
131+
132 /*
133 * This used to trigger the assert in lsi_do_dma()
134 * https://bugs.launchpad.net/qemu/+bug/697510
135@@ -48,5 +121,8 @@ int main(int argc, char **argv)
136 test_lsi_do_dma_empty_queue);
137 }
138
139+ qtest_add_func("fuzz/lsi53c895a/lsi_do_msgout_cancel_req",
140+ test_lsi_do_msgout_cancel_req);
141+
142 return g_test_run();
143 }
144--
1452.33.0
146