[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 13/41] megasas: always store SCSIRequest* into Megasa
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PULL 13/41] megasas: always store SCSIRequest* into MegasasCmd |
Date: |
Thu, 15 Jun 2017 12:52:33 +0200 |
This ensures that the request is unref'ed properly, and avoids a
segmentation fault in the new qtest testcase that is added.
This is CVE-2017-9503.
Reported-by: Zhangyanyu <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
hw/scsi/megasas.c | 31 ++++++++++++++++---------------
tests/megasas-test.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 15 deletions(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 135662d..734fdae 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -609,6 +609,9 @@ static void megasas_reset_frames(MegasasState *s)
static void megasas_abort_command(MegasasCmd *cmd)
{
/* Never abort internal commands. */
+ if (cmd->dcmd_opcode != -1) {
+ return;
+ }
if (cmd->req != NULL) {
scsi_req_cancel(cmd->req);
}
@@ -1017,7 +1020,6 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev,
int lun,
uint64_t pd_size;
uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
uint8_t cmdbuf[6];
- SCSIRequest *req;
size_t len, resid;
if (!cmd->iov_buf) {
@@ -1026,8 +1028,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev,
int lun,
info->inquiry_data[0] = 0x7f; /* Force PQual 0x3, PType 0x1f */
info->vpd_page83[0] = 0x7f;
megasas_setup_inquiry(cmdbuf, 0, sizeof(info->inquiry_data));
- req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd);
- if (!req) {
+ cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd);
+ if (!cmd->req) {
trace_megasas_dcmd_req_alloc_failed(cmd->index,
"PD get info std inquiry");
g_free(cmd->iov_buf);
@@ -1036,26 +1038,26 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev,
int lun,
}
trace_megasas_dcmd_internal_submit(cmd->index,
"PD get info std inquiry", lun);
- len = scsi_req_enqueue(req);
+ len = scsi_req_enqueue(cmd->req);
if (len > 0) {
cmd->iov_size = len;
- scsi_req_continue(req);
+ scsi_req_continue(cmd->req);
}
return MFI_STAT_INVALID_STATUS;
} else if (info->inquiry_data[0] != 0x7f && info->vpd_page83[0] == 0x7f) {
megasas_setup_inquiry(cmdbuf, 0x83, sizeof(info->vpd_page83));
- req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd);
- if (!req) {
+ cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd);
+ if (!cmd->req) {
trace_megasas_dcmd_req_alloc_failed(cmd->index,
"PD get info vpd inquiry");
return MFI_STAT_FLASH_ALLOC_FAIL;
}
trace_megasas_dcmd_internal_submit(cmd->index,
"PD get info vpd inquiry", lun);
- len = scsi_req_enqueue(req);
+ len = scsi_req_enqueue(cmd->req);
if (len > 0) {
cmd->iov_size = len;
- scsi_req_continue(req);
+ scsi_req_continue(cmd->req);
}
return MFI_STAT_INVALID_STATUS;
}
@@ -1217,7 +1219,6 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev,
int lun,
struct mfi_ld_info *info = cmd->iov_buf;
size_t dcmd_size = sizeof(struct mfi_ld_info);
uint8_t cdb[6];
- SCSIRequest *req;
ssize_t len, resid;
uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF);
uint64_t ld_size;
@@ -1226,8 +1227,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev,
int lun,
cmd->iov_buf = g_malloc0(dcmd_size);
info = cmd->iov_buf;
megasas_setup_inquiry(cdb, 0x83, sizeof(info->vpd_page83));
- req = scsi_req_new(sdev, cmd->index, lun, cdb, cmd);
- if (!req) {
+ cmd->req = scsi_req_new(sdev, cmd->index, lun, cdb, cmd);
+ if (!cmd->req) {
trace_megasas_dcmd_req_alloc_failed(cmd->index,
"LD get info vpd inquiry");
g_free(cmd->iov_buf);
@@ -1236,10 +1237,10 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev,
int lun,
}
trace_megasas_dcmd_internal_submit(cmd->index,
"LD get info vpd inquiry", lun);
- len = scsi_req_enqueue(req);
+ len = scsi_req_enqueue(cmd->req);
if (len > 0) {
cmd->iov_size = len;
- scsi_req_continue(req);
+ scsi_req_continue(cmd->req);
}
return MFI_STAT_INVALID_STATUS;
}
@@ -1851,7 +1852,7 @@ static void megasas_command_complete(SCSIRequest *req,
uint32_t status,
return;
}
- if (cmd->req == NULL) {
+ if (cmd->dcmd_opcode != -1) {
/*
* Internal command complete
*/
diff --git a/tests/megasas-test.c b/tests/megasas-test.c
index a9e56a2..ce960e7 100644
--- a/tests/megasas-test.c
+++ b/tests/megasas-test.c
@@ -42,10 +42,45 @@ static void pci_nop(void)
qmegasas_stop(qs);
}
+/* This used to cause a NULL pointer dereference. */
+static void megasas_pd_get_info_fuzz(void)
+{
+ QPCIDevice *dev;
+ QOSState *qs;
+ QPCIBar bar;
+ uint32_t context[256];
+ uint64_t context_pa;
+ int i;
+
+ qs = qmegasas_start(NULL);
+ dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4,0));
+ g_assert(dev != NULL);
+
+ qpci_device_enable(dev);
+ bar = qpci_iomap(dev, 0, NULL);
+
+ memset(context, 0, sizeof(context));
+ context[0] = cpu_to_le32(0x05050505);
+ context[1] = cpu_to_le32(0x01010101);
+ for (i = 2; i < ARRAY_SIZE(context); i++) {
+ context[i] = cpu_to_le32(0x41414141);
+ }
+ context[6] = cpu_to_le32(0x02020000);
+ context[7] = cpu_to_le32(0);
+
+ context_pa = qmalloc(qs, sizeof(context));
+ memwrite(context_pa, context, sizeof(context));
+ qpci_io_writel(dev, bar, 0x40, context_pa);
+
+ g_free(dev);
+ qmegasas_stop(qs);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
qtest_add_func("/megasas/pci/nop", pci_nop);
+ qtest_add_func("/megasas/dcmd/pd-get-info/fuzz", megasas_pd_get_info_fuzz);
return g_test_run();
}
--
1.8.3.1
- [Qemu-devel] [PULL 08/41] megasas: do not read sense length more than once from frame, (continued)
- [Qemu-devel] [PULL 08/41] megasas: do not read sense length more than once from frame, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 06/41] memory: remove memory_region_set_fd, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 12/41] megasas: do not read SCSI req parameters more than once from frame, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 16/41] kvm-all: make async_safe_run_on_cpu safe on kvm too, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 09/41] megasas: do not read iovec count more than once from frame, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 14/41] Makefile: Do not generate files if "configure" has not been run yet, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 21/41] tcg: move tcg related files into accel/tcg/ subdirectory, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 20/41] accel: split the tcg accelerator from accel.c file, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 22/41] tcg: move tcg backend files into accel/tcg/, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 17/41] hax-all: make async_safe_run_on_cpu safe on HAX too, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 13/41] megasas: always store SCSIRequest* into MegasasCmd,
Paolo Bonzini <=
- [Qemu-devel] [PULL 15/41] vl: Fix broken thread=xxx option of the --accel parameter, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 25/41] nbd: make nbd_drop public, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 23/41] accel: move kvm related accelerator files into accel/, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 26/41] nbd/server: get rid of nbd_negotiate_read and friends, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 28/41] nbd/server: refactor nbd_co_send_reply, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 27/41] nbd/server: get rid of ssize_t, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 19/41] qemu-nbd: Ignore SIGPIPE, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 29/41] nbd/server: get rid of EAGAIN dead code, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 35/41] nbd/server: refactor nbd_trip, Paolo Bonzini, 2017/06/15
- [Qemu-devel] [PULL 10/41] megasas: do not read DCMD opcode more than once from frame, Paolo Bonzini, 2017/06/15