From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41590) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Vnsma-0005DQ-KA for qemu-devel@nongnu.org; Tue, 03 Dec 2013 11:25:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VnsmU-0006Xh-Mr for qemu-devel@nongnu.org; Tue, 03 Dec 2013 11:25:08 -0500 Date: Tue, 3 Dec 2013 18:28:30 +0200 From: "Michael S. Tsirkin" Message-ID: <1386087086-3691-4-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 03/23] virtio-net: out-of-bounds buffer write on invalid state load List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Jason Wang , qemu-stable@nongnu.org, Anthony Liguori , Michael Roth CVE-2013-4150 QEMU 1.5.0 out-of-bounds buffer write in virtio_net_load()@hw/net/virtio-net.c This code is in hw/net/virtio-net.c: if (n->max_queues > 1) { if (n->max_queues != qemu_get_be16(f)) { error_report("virtio-net: different max_queues "); return -1; } n->curr_queues = qemu_get_be16(f); for (i = 1; i < n->curr_queues; i++) { n->vqs[i].tx_waiting = qemu_get_be32(f); } } Number of vqs is max_queues, so if we get invalid input here, for example if max_queues = 2, curr_queues = 3, we get write beyond end of the buffer, with data that comes from wire. This might be used to corrupt qemu memory in hard to predict ways. Since we have lots of function pointers around, RCE might be possible. Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Reviewed-by: Michael Roth --- hw/net/virtio-net.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 2b92640..383c1f5 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1383,6 +1383,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) } n->curr_queues = qemu_get_be16(f); + if (n->curr_queues > n->max_queues) { + error_report("virtio-net: curr_queues %x > max_queues %x", + n->curr_queues, n->max_queues); + return -1; + } for (i = 1; i < n->curr_queues; i++) { n->vqs[i].tx_waiting = qemu_get_be32(f); } -- MST