9ae3a8
From dc546cbfdefb8ddbaf121d3b075ca723df264d1c Mon Sep 17 00:00:00 2001
9ae3a8
From: Vlad Yasevich <vyasevic@redhat.com>
9ae3a8
Date: Wed, 16 Dec 2015 02:58:22 +0100
9ae3a8
Subject: [PATCH 5/6] rtl8139: Fix receive buffer overflow check
9ae3a8
9ae3a8
Message-id: <1450234703-7606-2-git-send-email-vyasevic@redhat.com>
9ae3a8
Patchwork-id: 68617
9ae3a8
O-Subject: [RHEL7.3 qemu-kvm PATCH 1/2] rtl8139: Fix receive buffer overflow check
9ae3a8
Bugzilla: 1252757
9ae3a8
RH-Acked-by: Thomas Huth <thuth@redhat.com>
9ae3a8
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
9ae3a8
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
9ae3a8
9ae3a8
rtl8139_do_receive() tries to check for the overflow condition
9ae3a8
by making sure that packet_size + 8 does not exceed the
9ae3a8
available buffer space.  The issue here is that RxBuffAddr,
9ae3a8
used to calculate available buffer space, is aligned to a
9ae3a8
a 4 byte boundry after every update.  So it is possible that
9ae3a8
every packet ends up being slightly padded when written
9ae3a8
to the receive buffer.  This padding is not taken into
9ae3a8
account when checking for overflow and we may end up missing
9ae3a8
the overflow condition can causing buffer overwrite.
9ae3a8
9ae3a8
This patch takes alignment into consideration when
9ae3a8
checking for overflow condition.
9ae3a8
9ae3a8
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
9ae3a8
Reviewed-by: Jason Wang <jasowang@redhat.com>
9ae3a8
Message-id: 1441121206-6997-2-git-send-email-vyasevic@redhat.com
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
(cherry picked from commit fabdcd3392f16fc666b1d04fc1bbe5f1dbbf10a4)
9ae3a8
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/net/rtl8139.c | 6 ++++--
9ae3a8
 1 file changed, 4 insertions(+), 2 deletions(-)
9ae3a8
9ae3a8
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
9ae3a8
index 4f89328..6a167df 100644
9ae3a8
--- a/hw/net/rtl8139.c
9ae3a8
+++ b/hw/net/rtl8139.c
9ae3a8
@@ -1137,7 +1137,9 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
9ae3a8
 
9ae3a8
         /* if receiver buffer is empty then avail == 0 */
9ae3a8
 
9ae3a8
-        if (avail != 0 && size + 8 >= avail)
9ae3a8
+#define RX_ALIGN(x) (((x) + 3) & ~0x3)
9ae3a8
+
9ae3a8
+        if (avail != 0 && RX_ALIGN(size + 8) >= avail)
9ae3a8
         {
9ae3a8
             DPRINTF("rx overflow: rx buffer length %d head 0x%04x "
9ae3a8
                 "read 0x%04x === available 0x%04x need 0x%04x\n",
9ae3a8
@@ -1165,7 +1167,7 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
9ae3a8
         rtl8139_write_buffer(s, (uint8_t *)&val, 4);
9ae3a8
 
9ae3a8
         /* correct buffer write pointer */
9ae3a8
-        s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize);
9ae3a8
+        s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);
9ae3a8
 
9ae3a8
         /* now we can signal we have received something */
9ae3a8
 
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8