CVE-2016-4002: net: buffer overflow in MIPSnet (bz #1326083)

CVE-2016-4952 scsi: pvscsi: out-of-bounds access issue
CVE-2016-5106: scsi: megasas: out-of-bounds write (bz #1339581)
CVE-2016-5105: scsi: megasas: stack information leakage (bz #1339585)
CVE-2016-5107: scsi: megasas: out-of-bounds read (bz #1339573)
CVE-2016-4454: display: vmsvga: out-of-bounds read (bz #1340740)
CVE-2016-4453: display: vmsvga: infinite loop (bz #1340744)
CVE-2016-5238: scsi: esp: OOB write (bz #1341932)
CVE-2016-5338: scsi: esp: OOB r/w access (bz #1343325)
CVE-2016-5337: scsi: megasas: information leakage (bz #1343910)
This commit is contained in:
Cole Robinson 2016-06-22 10:15:02 -04:00
parent 85f4aff1ee
commit 9b48605ba7
15 changed files with 789 additions and 1 deletions

View File

@ -0,0 +1,32 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Thu, 7 Apr 2016 15:56:02 +0530
Subject: [PATCH] net: mipsnet: check packet length against buffer
When receiving packets over MIPSnet network device, it uses
receive buffer of size 1514 bytes. In case the controller
accepts large(MTU) packets, it could lead to memory corruption.
Add check to avoid it.
Reported by: Oleksandr Bazhaniuk <oleksandr.bazhaniuk@intel.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry picked from commit 3af9187fc6caaf415ab9c0c6d92c9678f65cb17f)
---
hw/net/mipsnet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
index c813e0c..e0973f2 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -82,6 +82,9 @@ static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t si
if (!mipsnet_can_receive(nc))
return -1;
+ if (size >= sizeof(s->rx_buffer)) {
+ return 0;
+ }
s->busy = 1;
/* Just accept everything. */

View File

@ -0,0 +1,100 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Mon, 23 May 2016 16:18:05 +0530
Subject: [PATCH] scsi: pvscsi: check command descriptor ring buffer size
(CVE-2016-4952)
Vmware Paravirtual SCSI emulation uses command descriptors to
process SCSI commands. These descriptors come with their ring
buffers. A guest could set the ring buffer size to an arbitrary
value leading to OOB access issue. Add check to avoid it.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Cc: qemu-stable@nongnu.org
Message-Id: <1464000485-27041-1-git-send-email-ppandit@redhat.com>
Reviewed-by: Shmulik Ladkani <shmulik.ladkani@ravellosystems.com>
Reviewed-by: Dmitry Fleytman <dmitry@daynix.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 3e831b40e015ba34dfb55ff11f767001839425ff)
---
hw/scsi/vmw_pvscsi.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index c6148d3..2596d71 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -126,7 +126,7 @@ pvscsi_log2(uint32_t input)
return log;
}
-static void
+static int
pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
{
int i;
@@ -134,6 +134,10 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
uint32_t req_ring_size, cmp_ring_size;
m->rs_pa = ri->ringsStatePPN << VMW_PAGE_SHIFT;
+ if ((ri->reqRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)
+ || (ri->cmpRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)) {
+ return -1;
+ }
req_ring_size = ri->reqRingNumPages * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
cmp_ring_size = ri->cmpRingNumPages * PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE;
txr_len_log2 = pvscsi_log2(req_ring_size - 1);
@@ -165,15 +169,20 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri)
/* Flush ring state page changes */
smp_wmb();
+
+ return 0;
}
-static void
+static int
pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)
{
int i;
uint32_t len_log2;
uint32_t ring_size;
+ if (ri->numPages > PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES) {
+ return -1;
+ }
ring_size = ri->numPages * PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE;
len_log2 = pvscsi_log2(ring_size - 1);
@@ -193,6 +202,8 @@ pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)
/* Flush ring state page changes */
smp_wmb();
+
+ return 0;
}
static void
@@ -743,7 +754,10 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s)
trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS");
pvscsi_dbg_dump_tx_rings_config(rc);
- pvscsi_ring_init_data(&s->rings, rc);
+ if (pvscsi_ring_init_data(&s->rings, rc) < 0) {
+ return PVSCSI_COMMAND_PROCESSING_FAILED;
+ }
+
s->rings_info_valid = TRUE;
return PVSCSI_COMMAND_PROCESSING_SUCCEEDED;
}
@@ -823,7 +837,9 @@ pvscsi_on_cmd_setup_msg_ring(PVSCSIState *s)
}
if (s->rings_info_valid) {
- pvscsi_ring_init_msg(&s->rings, rc);
+ if (pvscsi_ring_init_msg(&s->rings, rc) < 0) {
+ return PVSCSI_COMMAND_PROCESSING_FAILED;
+ }
s->msg_ring_info_valid = TRUE;
}
return sizeof(PVSCSICmdDescSetupMsgRing) / sizeof(uint32_t);

View File

@ -0,0 +1,31 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Wed, 25 May 2016 16:01:29 +0530
Subject: [PATCH] scsi: megasas: use appropriate property buffer size
When setting MegaRAID SAS controller properties via MegaRAID
Firmware Interface(MFI) commands, a user supplied size parameter
is used to set property value. Use appropriate size value to avoid
OOB access issues.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1464172291-2856-2-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 1b85898025c4cd95dce673d15e67e60e98e91731)
---
hw/scsi/megasas.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index 108448e..ba62adf 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1445,7 +1445,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd)
dcmd_size);
return MFI_STAT_INVALID_PARAMETER;
}
- dma_buf_write((uint8_t *)&info, cmd->iov_size, &cmd->qsg);
+ dma_buf_write((uint8_t *)&info, dcmd_size, &cmd->qsg);
trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size);
return MFI_STAT_OK;
}

View File

@ -0,0 +1,31 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Wed, 25 May 2016 17:41:44 +0530
Subject: [PATCH] scsi: megasas: initialise local configuration data buffer
When reading MegaRAID SAS controller configuration via MegaRAID
Firmware Interface(MFI) commands, routine megasas_dcmd_cfg_read
uses an uninitialised local data buffer. Initialise this buffer
to avoid stack information leakage.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1464178304-12831-1-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d37af740730dbbb93960cd318e040372d04d6dcf)
---
hw/scsi/megasas.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index ba62adf..c746a7e 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -1292,7 +1292,7 @@ static int megasas_dcmd_ld_get_info(MegasasState *s, MegasasCmd *cmd)
static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
{
- uint8_t data[4096];
+ uint8_t data[4096] = { 0 };
struct mfi_config_data *info;
int num_pd_disks = 0, array_offset, ld_offset;
BusChild *kid;

View File

@ -0,0 +1,33 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Wed, 25 May 2016 17:55:10 +0530
Subject: [PATCH] scsi: megasas: check 'read_queue_head' index value
While doing MegaRAID SAS controller command frame lookup, routine
'megasas_lookup_frame' uses 'read_queue_head' value as an index
into 'frames[MEGASAS_MAX_FRAMES=2048]' array. Limit its value
within array bounds to avoid any OOB access.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1464179110-18593-1-git-send-email-ppandit@redhat.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit b60bdd1f1ee1616b7a9aeeffb4088e1ce2710fb2)
---
hw/scsi/megasas.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index c746a7e..bcb1a0c 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -649,7 +649,9 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd)
pa_hi = le32_to_cpu(initq->pi_addr_hi);
s->producer_pa = ((uint64_t) pa_hi << 32) | pa_lo;
s->reply_queue_head = ldl_le_pci_dma(pcid, s->producer_pa);
+ s->reply_queue_head %= MEGASAS_MAX_FRAMES;
s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa);
+ s->reply_queue_tail %= MEGASAS_MAX_FRAMES;
flags = le32_to_cpu(initq->flags);
if (flags & MFI_QUEUE_FLAG_CONTEXT64) {
s->flags |= MEGASAS_MASK_USE_QUEUE64;

View File

@ -0,0 +1,70 @@
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 30 May 2016 09:09:18 +0200
Subject: [PATCH] vmsvga: move fifo sanity checks to vmsvga_fifo_length
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Sanity checks are applied when the fifo is enabled by the guest
(SVGA_REG_CONFIG_DONE write). Which doesn't help much if the guest
changes the fifo registers afterwards. Move the checks to
vmsvga_fifo_length so they are done each time qemu is about to read
from the fifo.
Fixes: CVE-2016-4454
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-2-git-send-email-kraxel@redhat.com
(cherry picked from commit 521360267876d3b6518b328051a2e56bca55bef8)
---
hw/display/vmware_vga.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index c17ddd1..b12128a 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -553,6 +553,21 @@ static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
if (!s->config || !s->enable) {
return 0;
}
+
+ /* Check range and alignment. */
+ if ((CMD(min) | CMD(max) | CMD(next_cmd) | CMD(stop)) & 3) {
+ return 0;
+ }
+ if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) {
+ return 0;
+ }
+ if (CMD(max) > SVGA_FIFO_SIZE) {
+ return 0;
+ }
+ if (CMD(max) < CMD(min) + 10 * 1024) {
+ return 0;
+ }
+
num = CMD(next_cmd) - CMD(stop);
if (num < 0) {
num += CMD(max) - CMD(min);
@@ -1000,19 +1015,6 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
case SVGA_REG_CONFIG_DONE:
if (value) {
s->fifo = (uint32_t *) s->fifo_ptr;
- /* Check range and alignment. */
- if ((CMD(min) | CMD(max) | CMD(next_cmd) | CMD(stop)) & 3) {
- break;
- }
- if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) {
- break;
- }
- if (CMD(max) > SVGA_FIFO_SIZE) {
- break;
- }
- if (CMD(max) < CMD(min) + 10 * 1024) {
- break;
- }
vga_dirty_log_stop(&s->vga);
}
s->config = !!value;

View File

@ -0,0 +1,36 @@
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 30 May 2016 09:09:19 +0200
Subject: [PATCH] vmsvga: add more fifo checks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Make sure all fifo ptrs are within range.
Fixes: CVE-2016-4454
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-3-git-send-email-kraxel@redhat.com
(cherry picked from commit c2e3c54d3960bc53bfa3a5ce7ea7a050b9be267e)
---
hw/display/vmware_vga.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index b12128a..0329d9f 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -561,7 +561,10 @@ static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) {
return 0;
}
- if (CMD(max) > SVGA_FIFO_SIZE) {
+ if (CMD(max) > SVGA_FIFO_SIZE ||
+ CMD(min) >= SVGA_FIFO_SIZE ||
+ CMD(stop) >= SVGA_FIFO_SIZE ||
+ CMD(next_cmd) >= SVGA_FIFO_SIZE) {
return 0;
}
if (CMD(max) < CMD(min) + 10 * 1024) {

View File

@ -0,0 +1,143 @@
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 30 May 2016 09:09:20 +0200
Subject: [PATCH] vmsvga: shadow fifo registers
The fifo is normal ram. So kvm vcpu threads and qemu iothread can
access the fifo in parallel without syncronization. Which in turn
implies we can't use the fifo pointers in-place because the guest
can try changing them underneath us. So add shadows for them, to
make sure the guest can't modify them after we've applied sanity
checks.
Fixes: CVE-2016-4454
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-4-git-send-email-kraxel@redhat.com
(cherry picked from commit 7e486f7577764a07aa35588e119903c80a5c30a2)
---
hw/display/vmware_vga.c | 57 ++++++++++++++++++++++++-------------------------
1 file changed, 28 insertions(+), 29 deletions(-)
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 0329d9f..8b9feb8 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -64,17 +64,11 @@ struct vmsvga_state_s {
uint8_t *fifo_ptr;
unsigned int fifo_size;
- union {
- uint32_t *fifo;
- struct QEMU_PACKED {
- uint32_t min;
- uint32_t max;
- uint32_t next_cmd;
- uint32_t stop;
- /* Add registers here when adding capabilities. */
- uint32_t fifo[0];
- } *cmd;
- };
+ uint32_t *fifo;
+ uint32_t fifo_min;
+ uint32_t fifo_max;
+ uint32_t fifo_next;
+ uint32_t fifo_stop;
#define REDRAW_FIFO_LEN 512
struct vmsvga_rect_s {
@@ -196,7 +190,7 @@ enum {
*/
SVGA_FIFO_MIN = 0,
SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */
- SVGA_FIFO_NEXT_CMD,
+ SVGA_FIFO_NEXT,
SVGA_FIFO_STOP,
/*
@@ -544,8 +538,6 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
}
#endif
-#define CMD(f) le32_to_cpu(s->cmd->f)
-
static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
{
int num;
@@ -554,38 +546,44 @@ static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
return 0;
}
+ s->fifo_min = le32_to_cpu(s->fifo[SVGA_FIFO_MIN]);
+ s->fifo_max = le32_to_cpu(s->fifo[SVGA_FIFO_MAX]);
+ s->fifo_next = le32_to_cpu(s->fifo[SVGA_FIFO_NEXT]);
+ s->fifo_stop = le32_to_cpu(s->fifo[SVGA_FIFO_STOP]);
+
/* Check range and alignment. */
- if ((CMD(min) | CMD(max) | CMD(next_cmd) | CMD(stop)) & 3) {
+ if ((s->fifo_min | s->fifo_max | s->fifo_next | s->fifo_stop) & 3) {
return 0;
}
- if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) {
+ if (s->fifo_min < sizeof(uint32_t) * 4) {
return 0;
}
- if (CMD(max) > SVGA_FIFO_SIZE ||
- CMD(min) >= SVGA_FIFO_SIZE ||
- CMD(stop) >= SVGA_FIFO_SIZE ||
- CMD(next_cmd) >= SVGA_FIFO_SIZE) {
+ if (s->fifo_max > SVGA_FIFO_SIZE ||
+ s->fifo_min >= SVGA_FIFO_SIZE ||
+ s->fifo_stop >= SVGA_FIFO_SIZE ||
+ s->fifo_next >= SVGA_FIFO_SIZE) {
return 0;
}
- if (CMD(max) < CMD(min) + 10 * 1024) {
+ if (s->fifo_max < s->fifo_min + 10 * 1024) {
return 0;
}
- num = CMD(next_cmd) - CMD(stop);
+ num = s->fifo_next - s->fifo_stop;
if (num < 0) {
- num += CMD(max) - CMD(min);
+ num += s->fifo_max - s->fifo_min;
}
return num >> 2;
}
static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s)
{
- uint32_t cmd = s->fifo[CMD(stop) >> 2];
+ uint32_t cmd = s->fifo[s->fifo_stop >> 2];
- s->cmd->stop = cpu_to_le32(CMD(stop) + 4);
- if (CMD(stop) >= CMD(max)) {
- s->cmd->stop = s->cmd->min;
+ s->fifo_stop += 4;
+ if (s->fifo_stop >= s->fifo_max) {
+ s->fifo_stop = s->fifo_min;
}
+ s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop);
return cmd;
}
@@ -605,7 +603,7 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
len = vmsvga_fifo_length(s);
while (len > 0) {
/* May need to go back to the start of the command if incomplete */
- cmd_start = s->cmd->stop;
+ cmd_start = s->fifo_stop;
switch (cmd = vmsvga_fifo_read(s)) {
case SVGA_CMD_UPDATE:
@@ -761,7 +759,8 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
break;
rewind:
- s->cmd->stop = cmd_start;
+ s->fifo_stop = cmd_start;
+ s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop);
break;
}
}

View File

@ -0,0 +1,42 @@
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 30 May 2016 09:09:21 +0200
Subject: [PATCH] vmsvga: don't process more than 1024 fifo commands at once
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
vmsvga_fifo_run is called in regular intervals (on each display update)
and will resume where it left off. So we can simply exit the loop,
without having to worry about how processing will continue.
Fixes: CVE-2016-4453
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-5-git-send-email-kraxel@redhat.com
(cherry picked from commit 4e68a0ee17dad7b8d870df0081d4ab2e079016c2)
---
hw/display/vmware_vga.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 8b9feb8..a856a97 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -595,13 +595,13 @@ static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
static void vmsvga_fifo_run(struct vmsvga_state_s *s)
{
uint32_t cmd, colour;
- int args, len;
+ int args, len, maxloop = 1024;
int x, y, dx, dy, width, height;
struct vmsvga_cursor_definition_s cursor;
uint32_t cmd_start;
len = vmsvga_fifo_length(s);
- while (len > 0) {
+ while (len > 0 && --maxloop > 0) {
/* May need to go back to the start of the command if incomplete */
cmd_start = s->fifo_stop;

View File

@ -0,0 +1,33 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Tue, 31 May 2016 23:23:27 +0530
Subject: [PATCH] scsi: esp: check buffer length before reading scsi command
The 53C9X Fast SCSI Controller(FSC) comes with an internal 16-byte
FIFO buffer. It is used to handle command and data transfer.
Routine get_cmd() in non-DMA mode, uses 'ti_size' to read scsi
command into a buffer. Add check to validate command length against
buffer size to avoid any overrun.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1464717207-7549-1-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d3cdc49138c30be1d3c2f83d18f85d9fdee95f1a)
---
hw/scsi/esp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 63a2a01..e1a8090 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -96,6 +96,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen)
s->dma_memory_read(s->dma_opaque, buf, dmalen);
} else {
dmalen = s->ti_size;
+ if (dmalen > TI_BUFSZ) {
+ return 0;
+ }
memcpy(buf, s->ti_buf, dmalen);
buf[0] = buf[2] >> 5;
}

View File

@ -0,0 +1,26 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 14 Jun 2016 15:10:24 +0200
Subject: [PATCH] scsi: esp: respect FIFO invariant after message phase
The FIFO contains two bytes; hence the write ptr should be two bytes ahead
of the read pointer.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d020aa504cec8f525b55ba2ef982c09dc847c72e)
---
hw/scsi/esp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index e1a8090..65d1830 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -220,7 +220,7 @@ static void write_response(ESPState *s)
} else {
s->ti_size = 2;
s->ti_rptr = 0;
- s->ti_wptr = 0;
+ s->ti_wptr = 2;
s->rregs[ESP_RFLAGS] = 2;
}
esp_raise_irq(s);

View File

@ -0,0 +1,76 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 15 Jun 2016 14:29:33 +0200
Subject: [PATCH] scsi: esp: clean up handle_ti/esp_do_dma if s->do_cmd
Avoid duplicated code between esp_do_dma and handle_ti. esp_do_dma
has the same code that handle_ti contains after the call to esp_do_dma;
but the code in handle_ti is never reached because it is in an "else if".
Remove the else and also the pointless return.
esp_do_dma also has a partially dead assignment of the to_device
variable. Sink it to the point where it's actually used.
Finally, assert that the other caller of esp_do_dma (esp_transfer_data)
only transfers data and not a command. This is true because get_cmd
cancels the old request synchronously before its caller handle_satn_stop
sets do_cmd to 1.
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 7f0b6e114ae4e142e2b3dfc9fac138f4a30edc4f)
---
hw/scsi/esp.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 65d1830..7337d27 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -243,15 +243,10 @@ static void esp_do_dma(ESPState *s)
uint32_t len;
int to_device;
- to_device = (s->ti_size < 0);
len = s->dma_left;
if (s->do_cmd) {
trace_esp_do_dma(s->cmdlen, len);
s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
- s->ti_size = 0;
- s->cmdlen = 0;
- s->do_cmd = 0;
- do_cmd(s, s->cmdbuf);
return;
}
if (s->async_len == 0) {
@@ -261,6 +256,7 @@ static void esp_do_dma(ESPState *s)
if (len > s->async_len) {
len = s->async_len;
}
+ to_device = (s->ti_size < 0);
if (to_device) {
s->dma_memory_read(s->dma_opaque, s->async_buf, len);
} else {
@@ -316,6 +312,7 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len)
{
ESPState *s = req->hba_private;
+ assert(!s->do_cmd);
trace_esp_transfer_data(s->dma_left, s->ti_size);
s->async_len = len;
s->async_buf = scsi_req_get_buf(req);
@@ -356,13 +353,13 @@ static void handle_ti(ESPState *s)
s->dma_left = minlen;
s->rregs[ESP_RSTAT] &= ~STAT_TC;
esp_do_dma(s);
- } else if (s->do_cmd) {
+ }
+ if (s->do_cmd) {
trace_esp_handle_ti_cmd(s->cmdlen);
s->ti_size = 0;
s->cmdlen = 0;
s->do_cmd = 0;
do_cmd(s, s->cmdbuf);
- return;
}
}

View File

@ -0,0 +1,70 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Thu, 16 Jun 2016 00:22:35 +0200
Subject: [PATCH] scsi: esp: make cmdbuf big enough for maximum CDB size
While doing DMA read into ESP command buffer 's->cmdbuf', it could
write past the 's->cmdbuf' area, if it was transferring more than 16
bytes. Increase the command buffer size to 32, which is maximum when
's->do_cmd' is set, and add a check on 'len' to avoid OOB access.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 926cde5f3e4d2504ed161ed0cb771ac7cad6fd11)
---
hw/scsi/esp.c | 6 ++++--
include/hw/scsi/esp.h | 3 ++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 7337d27..a5f1095 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -246,6 +246,8 @@ static void esp_do_dma(ESPState *s)
len = s->dma_left;
if (s->do_cmd) {
trace_esp_do_dma(s->cmdlen, len);
+ assert (s->cmdlen <= sizeof(s->cmdbuf) &&
+ len <= sizeof(s->cmdbuf) - s->cmdlen);
s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
return;
}
@@ -343,7 +345,7 @@ static void handle_ti(ESPState *s)
s->dma_counter = dmalen;
if (s->do_cmd)
- minlen = (dmalen < 32) ? dmalen : 32;
+ minlen = (dmalen < ESP_CMDBUF_SZ) ? dmalen : ESP_CMDBUF_SZ;
else if (s->ti_size < 0)
minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
else
@@ -449,7 +451,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
break;
case ESP_FIFO:
if (s->do_cmd) {
- if (s->cmdlen < TI_BUFSZ) {
+ if (s->cmdlen < ESP_CMDBUF_SZ) {
s->cmdbuf[s->cmdlen++] = val & 0xff;
} else {
trace_esp_error_fifo_overrun();
diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h
index 6c79527..d2c4886 100644
--- a/include/hw/scsi/esp.h
+++ b/include/hw/scsi/esp.h
@@ -14,6 +14,7 @@ void esp_init(hwaddr espaddr, int it_shift,
#define ESP_REGS 16
#define TI_BUFSZ 16
+#define ESP_CMDBUF_SZ 32
typedef struct ESPState ESPState;
@@ -31,7 +32,7 @@ struct ESPState {
SCSIBus bus;
SCSIDevice *current_dev;
SCSIRequest *current_req;
- uint8_t cmdbuf[TI_BUFSZ];
+ uint8_t cmdbuf[ESP_CMDBUF_SZ];
uint32_t cmdlen;
uint32_t do_cmd;

View File

@ -0,0 +1,29 @@
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Tue, 7 Jun 2016 16:44:03 +0530
Subject: [PATCH] scsi: megasas: null terminate bios version buffer
While reading information via 'megasas_ctrl_get_info' routine,
a local bios version buffer isn't null terminated. Add the
terminating null byte to avoid any OOB access.
Reported-by: Li Qiang <liqiang6-s@360.cn>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 844864fbae66935951529408831c2f22367a57b6)
---
hw/scsi/megasas.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index bcb1a0c..6a80995 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -772,6 +772,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
ptr = memory_region_get_ram_ptr(&pci_dev->rom);
memcpy(biosver, ptr + 0x41, 31);
+ biosver[31] = 0;
memcpy(info.image_component[1].name, "BIOS", 4);
memcpy(info.image_component[1].version, biosver,
strlen((const char *)biosver));

View File

@ -43,7 +43,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 2.3.1
Release: 15%{?dist}
Release: 16%{?dist}
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
Group: Development/Tools
@ -209,6 +209,30 @@ Patch0126: 0126-esp-check-command-buffer-length-before-write-CVE-201.patch
Patch0127: 0127-esp-check-dma-length-before-reading-scsi-command-CVE.patch
# Fix regression installing windows 7 with qxl/vga (bz #1339267)
Patch0128: 0128-vga-add-sr_vbe-register-set.patch
# CVE-2016-4002: net: buffer overflow in MIPSnet (bz #1326083)
Patch0129: 0129-net-mipsnet-check-packet-length-against-buffer.patch
# CVE-2016-4952 scsi: pvscsi: out-of-bounds access issue
Patch0130: 0130-scsi-pvscsi-check-command-descriptor-ring-buffer-siz.patch
# CVE-2016-5106: scsi: megasas: out-of-bounds write (bz #1339581)
Patch0131: 0131-scsi-megasas-use-appropriate-property-buffer-size.patch
# CVE-2016-5105: scsi: megasas: stack information leakage (bz #1339585)
Patch0132: 0132-scsi-megasas-initialise-local-configuration-data-buf.patch
# CVE-2016-5107: scsi: megasas: out-of-bounds read (bz #1339573)
Patch0133: 0133-scsi-megasas-check-read_queue_head-index-value.patch
# CVE-2016-4454: display: vmsvga: out-of-bounds read (bz #1340740)
Patch0134: 0134-vmsvga-move-fifo-sanity-checks-to-vmsvga_fifo_length.patch
Patch0135: 0135-vmsvga-add-more-fifo-checks.patch
Patch0136: 0136-vmsvga-shadow-fifo-registers.patch
# CVE-2016-4453: display: vmsvga: infinite loop (bz #1340744)
Patch0137: 0137-vmsvga-don-t-process-more-than-1024-fifo-commands-at.patch
# CVE-2016-5238: scsi: esp: OOB write (bz #1341932)
Patch0138: 0138-scsi-esp-check-buffer-length-before-reading-scsi-com.patch
Patch0139: 0139-scsi-esp-respect-FIFO-invariant-after-message-phase.patch
Patch0140: 0140-scsi-esp-clean-up-handle_ti-esp_do_dma-if-s-do_cmd.patch
# CVE-2016-5338: scsi: esp: OOB r/w access (bz #1343325)
Patch0141: 0141-scsi-esp-make-cmdbuf-big-enough-for-maximum-CDB-size.patch
# CVE-2016-5337: scsi: megasas: information leakage (bz #1343910)
Patch0142: 0142-scsi-megasas-null-terminate-bios-version-buffer.patch
BuildRequires: SDL2-devel
BuildRequires: zlib-devel
@ -1311,6 +1335,18 @@ getent passwd qemu >/dev/null || \
%changelog
* Wed Jun 22 2016 Cole Robinson <crobinso@redhat.com> - 2:2.3.1-16
- CVE-2016-4002: net: buffer overflow in MIPSnet (bz #1326083)
- CVE-2016-4952 scsi: pvscsi: out-of-bounds access issue
- CVE-2016-5106: scsi: megasas: out-of-bounds write (bz #1339581)
- CVE-2016-5105: scsi: megasas: stack information leakage (bz #1339585)
- CVE-2016-5107: scsi: megasas: out-of-bounds read (bz #1339573)
- CVE-2016-4454: display: vmsvga: out-of-bounds read (bz #1340740)
- CVE-2016-4453: display: vmsvga: infinite loop (bz #1340744)
- CVE-2016-5238: scsi: esp: OOB write (bz #1341932)
- CVE-2016-5338: scsi: esp: OOB r/w access (bz #1343325)
- CVE-2016-5337: scsi: megasas: information leakage (bz #1343910)
* Thu May 26 2016 Cole Robinson <crobinso@redhat.com> - 2:2.3.1-15
- CVE-2016-4020: memory leak in kvmvapic.c (bz #1326904)
- CVE-2016-4439: scsi: esb: OOB write #1 (bz #1337503)