Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 335

kvm-83-270.el5_11.src.rpm

From ae650570c1097045107e380c281062b1890726d2 Mon Sep 17 00:00:00 2001
From: Jason Wang <jasowang@redhat.com>
Date: Mon, 16 Jan 2012 12:52:59 +0800
Subject: [PATCH] e1000: prevent buffer overflow when processing legacy
 descriptors

Bugzilla:https://bugzilla.redhat.com/show_bug.cgi?id=772080 (5.8)
         https://bugzilla.redhat.com/show_bug.cgi?id=772079 (5.7z)
Upstream: N/A (The embargo lift date is 2012-01-23)
Test status:
This issue is reproduced by qtest originally. And I test this by
hacking the guest driver to remove EOP and fill 0xffff for length then
using gdb to check buffer overflow and ping for netperf functionality.

There isn't proper checking in legacy mode packets such that if two
large packets arrive back to back without the EOP flag set in the
first packet, you can easily overrun your buffer.

Because data is written to the packets after the packet is processed,
this could allow a heap overflow which is exploitable.

Add a check before copy to solve this issue.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 qemu/hw/e1000.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/qemu/hw/e1000.c b/qemu/hw/e1000.c
index 65db8a5..cb6c15b 100644
--- a/qemu/hw/e1000.c
+++ b/qemu/hw/e1000.c
@@ -454,6 +454,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
             bytes = split_size;
             if (tp->size + bytes > msh)
                 bytes = msh - tp->size;
+            bytes = MIN(sizeof(tp->data) - tp->size, bytes);
             cpu_physical_memory_read(addr, tp->data + tp->size, bytes);
             if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
                 memmove(tp->header, tp->data, hdr);
@@ -469,6 +470,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
         // context descriptor TSE is not set, while data descriptor TSE is set
         DBGOUT(TXERR, "TCP segmentaion Error\n");
     } else {
+        split_size = MIN(sizeof(tp->data) - tp->size, split_size);
         cpu_physical_memory_read(addr, tp->data + tp->size, split_size);
         tp->size += split_size;
     }
-- 
1.7.7.4