yeahuh / rpms / qemu-kvm

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