[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 03/39] scsi: Reject commands if the CDB length exceeds buf_len
From: |
Paolo Bonzini |
Subject: |
[PULL 03/39] scsi: Reject commands if the CDB length exceeds buf_len |
Date: |
Thu, 1 Sep 2022 20:23:53 +0200 |
From: John Millikin <john@john-millikin.com>
In scsi_req_parse_cdb(), if the CDB length implied by the command type
exceeds the initialized portion of the command buffer, reject the request.
Rejected requests are recorded by the `scsi_req_parse_bad` trace event.
On example of a bug detected by this check is SunOS's use of interleaved
DMA and non-DMA commands. This guest behavior currently causes QEMU to
parse uninitialized memory as a SCSI command, with unpredictable
outcomes.
With the new check in place:
* QEMU consistently creates a trace event and rejects the request.
* SunOS retries the request(s) and is able to successfully boot from
disk.
Signed-off-by: John Millikin <john@john-millikin.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1127
Message-Id: <20220817053458.698416-2-john@john-millikin.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi/scsi-bus.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index cc71524024..4403717c4a 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -712,6 +712,11 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag,
uint32_t lun,
SCSICommand cmd = { .len = 0 };
int ret;
+ if (buf_len == 0) {
+ trace_scsi_req_parse_bad(d->id, lun, tag, 0);
+ goto invalid_opcode;
+ }
+
if ((d->unit_attention.key == UNIT_ATTENTION ||
bus->unit_attention.key == UNIT_ATTENTION) &&
(buf[0] != INQUIRY &&
@@ -741,6 +746,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag,
uint32_t lun,
if (ret != 0) {
trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]);
+invalid_opcode:
req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private);
} else {
assert(cmd.len != 0);
@@ -1316,7 +1322,7 @@ int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
uint8_t *buf,
cmd->lba = -1;
len = scsi_cdb_length(buf);
- if (len < 0) {
+ if (len < 0 || len > buf_len) {
return -1;
}
--
2.37.2
- [PULL 00/39] i386, SCSI, build system changes for 2022-09-01, Paolo Bonzini, 2022/09/01
- [PULL 01/39] esp: Handle CMD_BUSRESET by resetting the SCSI bus, Paolo Bonzini, 2022/09/01
- [PULL 03/39] scsi: Reject commands if the CDB length exceeds buf_len,
Paolo Bonzini <=
- [PULL 04/39] i386: reset KVM nested state upon CPU reset, Paolo Bonzini, 2022/09/01
- [PULL 02/39] scsi: Add buf_len parameter to scsi_req_new(), Paolo Bonzini, 2022/09/01
- [PULL 06/39] configure: improve error for ucontext coroutine backend, Paolo Bonzini, 2022/09/01
- [PULL 05/39] i386: do kvm_put_msr_feature_control() first thing when vCPU is reset, Paolo Bonzini, 2022/09/01
- [PULL 07/39] meson: be strict for boolean options, Paolo Bonzini, 2022/09/01
- [PULL 08/39] meson: remove dead code, Paolo Bonzini, 2022/09/01
- [PULL 11/39] tests/tcg: x86_64: improve consistency with i386, Paolo Bonzini, 2022/09/01
- [PULL 10/39] KVM: dirty ring: add missing memory barrier, Paolo Bonzini, 2022/09/01
- [PULL 09/39] meson: remove dead assignments, Paolo Bonzini, 2022/09/01
- [PULL 14/39] target/i386: DPPS rounding fix, Paolo Bonzini, 2022/09/01