thebeanogamer / rpms / qemu-kvm

Forked from rpms/qemu-kvm 5 months ago
Clone
9ae3a8
From 5ec13dc4ed1c536de9711cb05af88609d073abf9 Mon Sep 17 00:00:00 2001
9ae3a8
From: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Date: Fri, 31 Jul 2015 15:59:42 +0200
9ae3a8
Subject: [PATCH 07/13] rtl8139: avoid nested ifs in IP header parsing
9ae3a8
 (CVE-2015-5165)
9ae3a8
9ae3a8
Message-id: <1438358388-10575-2-git-send-email-stefanha@redhat.com>
9ae3a8
Patchwork-id: 67236
9ae3a8
O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing (CVE-2015-5165)
9ae3a8
Bugzilla: 1248766
9ae3a8
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9ae3a8
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
9ae3a8
Transmit offload needs to parse packet headers.  If header fields have
9ae3a8
unexpected values the offload processing is skipped.
9ae3a8
9ae3a8
The code currently uses nested ifs because there is relatively little
9ae3a8
input validation.  The next patches will add missing input validation
9ae3a8
and a goto label is more appropriate to avoid deep if statement nesting.
9ae3a8
9ae3a8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/net/rtl8139.c | 41 ++++++++++++++++++++++-------------------
9ae3a8
 1 file changed, 22 insertions(+), 19 deletions(-)
9ae3a8
9ae3a8
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
9ae3a8
index d08106b..e3b594f 100644
9ae3a8
--- a/hw/net/rtl8139.c
9ae3a8
+++ b/hw/net/rtl8139.c
9ae3a8
@@ -2152,28 +2152,30 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
9ae3a8
             size_t   eth_payload_len  = 0;
9ae3a8
 
9ae3a8
             int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
9ae3a8
-            if (proto == ETH_P_IP)
9ae3a8
+            if (proto != ETH_P_IP)
9ae3a8
             {
9ae3a8
-                DPRINTF("+++ C+ mode has IP packet\n");
9ae3a8
-
9ae3a8
-                /* not aligned */
9ae3a8
-                eth_payload_data = saved_buffer + ETH_HLEN;
9ae3a8
-                eth_payload_len  = saved_size   - ETH_HLEN;
9ae3a8
-
9ae3a8
-                ip = (ip_header*)eth_payload_data;
9ae3a8
-
9ae3a8
-                if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
9ae3a8
-                    DPRINTF("+++ C+ mode packet has bad IP version %d "
9ae3a8
-                        "expected %d\n", IP_HEADER_VERSION(ip),
9ae3a8
-                        IP_HEADER_VERSION_4);
9ae3a8
-                    ip = NULL;
9ae3a8
-                } else {
9ae3a8
-                    hlen = IP_HEADER_LENGTH(ip);
9ae3a8
-                    ip_protocol = ip->ip_p;
9ae3a8
-                    ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
9ae3a8
-                }
9ae3a8
+                goto skip_offload;
9ae3a8
             }
9ae3a8
 
9ae3a8
+            DPRINTF("+++ C+ mode has IP packet\n");
9ae3a8
+
9ae3a8
+            /* not aligned */
9ae3a8
+            eth_payload_data = saved_buffer + ETH_HLEN;
9ae3a8
+            eth_payload_len  = saved_size   - ETH_HLEN;
9ae3a8
+
9ae3a8
+            ip = (ip_header*)eth_payload_data;
9ae3a8
+
9ae3a8
+            if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
9ae3a8
+                DPRINTF("+++ C+ mode packet has bad IP version %d "
9ae3a8
+                    "expected %d\n", IP_HEADER_VERSION(ip),
9ae3a8
+                    IP_HEADER_VERSION_4);
9ae3a8
+                goto skip_offload;
9ae3a8
+            }
9ae3a8
+
9ae3a8
+            hlen = IP_HEADER_LENGTH(ip);
9ae3a8
+            ip_protocol = ip->ip_p;
9ae3a8
+            ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
9ae3a8
+
9ae3a8
             if (ip)
9ae3a8
             {
9ae3a8
                 if (txdw0 & CP_TX_IPCS)
9ae3a8
@@ -2369,6 +2371,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
9ae3a8
             }
9ae3a8
         }
9ae3a8
 
9ae3a8
+skip_offload:
9ae3a8
         /* update tally counter */
9ae3a8
         ++s->tally_counters.TxOk;
9ae3a8
 
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8