Blame SOURCES/kvm-scsi-generic-avoid-possible-out-of-bounds-access-to-.patch

383d26
From afb03b05279fbb6e405ca1815e419f8ec3650a2c Mon Sep 17 00:00:00 2001
383d26
From: John Snow <jsnow@redhat.com>
383d26
Date: Wed, 6 Feb 2019 18:42:16 +0100
383d26
Subject: [PATCH 10/33] scsi-generic: avoid possible out-of-bounds access to
383d26
 r->buf
383d26
383d26
RH-Author: John Snow <jsnow@redhat.com>
383d26
Message-id: <20190206184216.15861-2-jsnow@redhat.com>
383d26
Patchwork-id: 84258
383d26
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 1/1] scsi-generic: avoid possible out-of-bounds access to r->buf
383d26
Bugzilla: 1668999
383d26
CVE: CVE-2019-6501/20190111
383d26
RH-Acked-by: Max Reitz <mreitz@redhat.com>
383d26
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
383d26
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
383d26
383d26
From: Paolo Bonzini <pbonzini@redhat.com>
383d26
383d26
Whenever the allocation length of a SCSI request is shorter than the size of the
383d26
VPD page list, page_idx is used blindly to index into r->buf.  Even though
383d26
the stores in the insertion sort are protected against overflows, the same is not
383d26
true of the reads and the final store of 0xb0.
383d26
383d26
This basically does the same thing as commit 57dbb58d80 ("scsi-generic: avoid
383d26
out-of-bounds access to VPD page list", 2018-11-06), except that here the
383d26
allocation length can be chosen by the guest.  Note that according to the SCSI
383d26
standard, the contents of the PAGE LENGTH field are not altered based
383d26
on the allocation length.
383d26
383d26
The code was introduced by commit 6c219fc8a1 ("scsi-generic: keep VPD
383d26
page list sorted", 2018-11-06) but the overflow was already possible before.
383d26
383d26
Reported-by: Kevin Wolf <kwolf@redhat.com>
383d26
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
383d26
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
383d26
Message-id: 20190111164506.15971-1-pbonzini@redhat.com
383d26
Fixes: a71c775b24ebc664129eb1d9b4c360590353efd5
383d26
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
383d26
Signed-off-by: John Snow <jsnow@redhat.com>
383d26
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
383d26
---
383d26
 hw/scsi/scsi-generic.c | 18 ++++++++++--------
383d26
 1 file changed, 10 insertions(+), 8 deletions(-)
383d26
383d26
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
383d26
index 4ac53e4..e21adf9 100644
383d26
--- a/hw/scsi/scsi-generic.c
383d26
+++ b/hw/scsi/scsi-generic.c
383d26
@@ -183,7 +183,7 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
383d26
             /* Also take care of the opt xfer len. */
383d26
             stl_be_p(&r->buf[12],
383d26
                     MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12])));
383d26
-        } else if (s->needs_vpd_bl_emulation && page == 0x00) {
383d26
+        } else if (s->needs_vpd_bl_emulation && page == 0x00 && r->buflen >= 4) {
383d26
             /*
383d26
              * Now we're capable of supplying the VPD Block Limits
383d26
              * response if the hardware can't. Add it in the INQUIRY
383d26
@@ -194,18 +194,20 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
383d26
              * and will use it to proper setup the SCSI device.
383d26
              *
383d26
              * VPD page numbers must be sorted, so insert 0xb0 at the
383d26
-             * right place with an in-place insert.  After the initialization
383d26
-             * part of the for loop is executed, the device response is
383d26
-             * at r[0] to r[page_idx - 1].
383d26
+             * right place with an in-place insert.  When the while loop
383d26
+             * begins the device response is at r[0] to r[page_idx - 1].
383d26
              */
383d26
-            for (page_idx = lduw_be_p(r->buf + 2) + 4;
383d26
-                 page_idx > 4 && r->buf[page_idx - 1] >= 0xb0;
383d26
-                 page_idx--) {
383d26
+            page_idx = lduw_be_p(r->buf + 2) + 4;
383d26
+            page_idx = MIN(page_idx, r->buflen);
383d26
+            while (page_idx > 4 && r->buf[page_idx - 1] >= 0xb0) {
383d26
                 if (page_idx < r->buflen) {
383d26
                     r->buf[page_idx] = r->buf[page_idx - 1];
383d26
                 }
383d26
+                page_idx--;
383d26
+            }
383d26
+            if (page_idx < r->buflen) {
383d26
+                r->buf[page_idx] = 0xb0;
383d26
             }
383d26
-            r->buf[page_idx] = 0xb0;
383d26
             stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
383d26
         }
383d26
     }
383d26
-- 
383d26
1.8.3.1
383d26