From 99caa32b6c4727bdf03271e62a41dda72d204e0a Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Mon, 16 Jan 2012 13:00:53 +0800 Subject: [PATCH] e1000: prevent buffer overflow when processing legacy descriptors Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=772086 https://bugzilla.redhat.com/show_bug.cgi?id=772081 (6.2z) Upstream: N/A (The embargo lift date is 2012-01-23) Test status: This issuse is originally reproduced through upstream qtest. For RHEL6, I have the guest e1000 driver by: 1) Clear the EOP flag for every packet. 2) Fill 0xFFFF for the descriptor length. By using this "malicious" driver, before applying this patch I get 2 segfaults of qemu after 3 times guest booting. After applying this patch, I get zero segfault for 3 times guest booting. 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 Signed-off-by: Michal Novotny --- hw/e1000.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index 708416a..9cf66ca 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -466,6 +466,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); @@ -481,6 +482,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