diff mbox series

[kirkstone,2/3] scsi-disk: ensure block size is non-zero and changes limited to bits 8-15

Message ID 20240212104647.376386-2-ppjadhav456@gmail.com
State Changes Requested
Delegated to: Steve Sakoman
Headers show
Series [kirkstone,1/3] scsi-disk: allow MODE SELECT block descriptor to set the block size | expand

Commit Message

Poonam Jadhav Feb. 12, 2024, 10:46 a.m. UTC
From: Poonam Jadhav <poonam.jadhav@kpit.com>

The existing code assumes that the block size can be generated from p[1] << 8
in multiple places which ignores the top and bottom 8 bits. If the block size
is allowed to be set to an arbitrary value then this causes a mismatch
between the value written by the guest in the block descriptor and the value
subsequently read back using READ CAPACITY causing the guest to generate
requests that can crash QEMU.

For now restrict block size changes to bits 8-15 and also ignore requests to
set the block size to 0 which causes the SCSI emulation to crash in at least
one place with a divide by zero error.
Link: https://github.com/qemu/qemu/commit/55794c904df723109b228da28b5db778e0df3110

Signed-off-by: Poonam Jadhav <poonam.jadhav@kpit.com>
---
 meta/recipes-devtools/qemu/qemu.inc           |  1 +
 ...ero-and-changes-limited-to-bits-8-15.patch | 67 +++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 meta/recipes-devtools/qemu/qemu/scsi-disk-ensure-block-size-is-non-zero-and-changes-limited-to-bits-8-15.patch
diff mbox series

Patch

diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index 13355238e8..9f85aa846c 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -104,6 +104,7 @@  SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
 	   file://CVE-2023-1544.patch \
 	   file://CVE-2023-5088.patch \
            file://scsi-disk-allow-MODE-SELECT-block-desriptor-to-set-the-block-size.patch \
+           file://scsi-disk-ensure-block-size-is-non-zero-and-changes-limited-to-bits-8-15.patch \
            "
 UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
 
diff --git a/meta/recipes-devtools/qemu/qemu/scsi-disk-ensure-block-size-is-non-zero-and-changes-limited-to-bits-8-15.patch b/meta/recipes-devtools/qemu/qemu/scsi-disk-ensure-block-size-is-non-zero-and-changes-limited-to-bits-8-15.patch
new file mode 100644
index 0000000000..1e1be683fc
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/scsi-disk-ensure-block-size-is-non-zero-and-changes-limited-to-bits-8-15.patch
@@ -0,0 +1,67 @@ 
+From 55794c904df723109b228da28b5db778e0df3110 Mon Sep 17 00:00:00 2001
+From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+Date: Sat, 30 Jul 2022 13:26:56 +0100
+Subject: [PATCH] scsi-disk: ensure block size is non-zero and changes limited
+ to bits 8-15
+
+The existing code assumes that the block size can be generated from p[1] << 8
+in multiple places which ignores the top and bottom 8 bits. If the block size
+is allowed to be set to an arbitrary value then this causes a mismatch
+between the value written by the guest in the block descriptor and the value
+subsequently read back using READ CAPACITY causing the guest to generate
+requests that can crash QEMU.
+
+For now restrict block size changes to bits 8-15 and also ignore requests to
+set the block size to 0 which causes the SCSI emulation to crash in at least
+one place with a divide by zero error.
+
+Fixes: 356c4c441e ("scsi-disk: allow MODE SELECT block descriptor to set the block size")
+Closes: https://gitlab.com/qemu-project/qemu/-/issues/1112
+Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
+Message-Id: <20220730122656.253448-3-mark.cave-ayland@ilande.co.uk>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+
+Comment: Patch is refreshed
+Upstream-Status: Backport [https://github.com/qemu/qemu/commit/55794c904df723109b228da28b5db778e0df3110]
+Signed-off-by: Poonam Jadhav <poonam.jadhav@kpit.com>
+---
+ hw/scsi/scsi-disk.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
+index 3027ac3b1ed6..efee6739f9ad 100644
+--- a/hw/scsi/scsi-disk.c
++++ b/hw/scsi/scsi-disk.c
+@@ -1532,7 +1532,7 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
+     int cmd = r->req.cmd.buf[0];
+     int len = r->req.cmd.xfer;
+     int hdr_len = (cmd == MODE_SELECT ? 4 : 8);
+-    int bd_len;
++    int bd_len, bs;
+     int pass;
+ 
+     /* We only support PF=1, SP=0.  */
+@@ -1617,9 +1617,19 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
+     }
+ 
+     /* Allow changing the block size */
+-    if (bd_len && p[6] != (s->qdev.blocksize >> 8)) {
+-        s->qdev.blocksize = p[6] << 8;
+-        trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize);
++    if (bd_len) {
++        bs = p[5] << 16 | p[6] << 8 | p[7];
++
++        /*
++         * Since the existing code only checks/updates bits 8-15 of the block
++         * size, restrict ourselves to the same requirement for now to ensure
++         * that a block size set by a block descriptor and then read back by
++         * a subsequent SCSI command will be the same
++         */
++        if (bs && !(bs & ~0xff00) && bs != s->qdev.blocksize) {
++            s->qdev.blocksize = bs;
++            trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize);
++        }
+     }
+ 
+     len -= bd_len;
+