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