From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41760) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vnsms-0005n5-Ji for qemu-devel@nongnu.org; Tue, 03 Dec 2013 11:25:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Vnsmm-0006kR-9l for qemu-devel@nongnu.org; Tue, 03 Dec 2013 11:25:26 -0500 Date: Tue, 3 Dec 2013 18:28:48 +0200 From: "Michael S. Tsirkin" Message-ID: <1386087086-3691-11-git-send-email-mst@redhat.com> References: <1386087086-3691-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1386087086-3691-1-git-send-email-mst@redhat.com> Subject: [Qemu-devel] [PATCH 10/23] stellaris_enet: avoid buffer overrun on incoming migration List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , qemu-stable@nongnu.org, Michael Roth From: Michael Roth CVE-2013-4532 s->next_packet is read from wire as an index into s->rx[]. If s->next_packet exceeds the length of s->rx[], the buffer can be subsequently overrun with arbitrary data from the wire. Fix this by introducing a constant that defines the length of s->rx[], and fail migration if the s->next_packet we read from the wire exceeds this. Signed-off-by: Michael Roth Signed-off-by: Michael S. Tsirkin --- hw/net/stellaris_enet.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 9dd77f7..db12a99 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -61,13 +61,14 @@ typedef struct { uint32_t np; int tx_frame_len; int tx_fifo_len; - uint8_t tx_fifo[2048]; /* Real hardware has a 2k fifo, which works out to be at most 31 packets. We implement a full 31 packet fifo. */ + uint8_t tx_fifo[2048]; +#define SE_RX_BUF_LEN 31 struct { uint8_t data[2048]; int len; - } rx[31]; + } rx[SE_RX_BUF_LEN]; uint8_t *rx_fifo; int rx_fifo_len; int next_packet; @@ -92,15 +93,15 @@ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, si if ((s->rctl & SE_RCTL_RXEN) == 0) return -1; - if (s->np >= 31) { + if (s->np >= SE_RX_BUF_LEN) { DPRINTF("Packet dropped\n"); return -1; } DPRINTF("Received packet len=%d\n", size); n = s->next_packet + s->np; - if (n >= 31) - n -= 31; + if (n >= SE_RX_BUF_LEN) + n -= SE_RX_BUF_LEN; s->np++; s->rx[n].len = size + 6; @@ -132,7 +133,7 @@ static int stellaris_enet_can_receive(NetClientState *nc) if ((s->rctl & SE_RCTL_RXEN) == 0) return 1; - return (s->np < 31); + return (s->np < SE_RX_BUF_LEN); } static uint64_t stellaris_enet_read(void *opaque, hwaddr offset, @@ -168,7 +169,7 @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset, if (s->rx_fifo_len <= 0) { s->rx_fifo_len = 0; s->next_packet++; - if (s->next_packet >= 31) + if (s->next_packet >= SE_RX_BUF_LEN) s->next_packet = 0; s->np--; DPRINTF("RX done np=%d\n", s->np); @@ -344,7 +345,7 @@ static void stellaris_enet_save(QEMUFile *f, void *opaque) qemu_put_be32(f, s->tx_frame_len); qemu_put_be32(f, s->tx_fifo_len); qemu_put_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); - for (i = 0; i < 31; i++) { + for (i = 0; i < SE_RX_BUF_LEN; i++) { qemu_put_be32(f, s->rx[i].len); qemu_put_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); @@ -375,12 +376,15 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) s->tx_frame_len = qemu_get_be32(f); s->tx_fifo_len = qemu_get_be32(f); qemu_get_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); - for (i = 0; i < 31; i++) { + for (i = 0; i < SE_RX_BUF_LEN; i++) { s->rx[i].len = qemu_get_be32(f); qemu_get_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); } s->next_packet = qemu_get_be32(f); + if (s->next_packet >= SE_RX_BUF_LEN) { + return -EINVAL; + } s->rx_fifo = s->rx[s->next_packet].data + qemu_get_be32(f); s->rx_fifo_len = qemu_get_be32(f); -- MST