]> xenbits.xensource.com Git - people/aperard/centos-package-xen.git/commitdiff
Import XSA-139, XSA-140
authorGeorge Dunlap <george.dunlap@eu.citrix.com>
Mon, 3 Aug 2015 11:27:41 +0000 (11:27 +0000)
committerGeorge Dunlap <george.dunlap@eu.citrix.com>
Mon, 3 Aug 2015 11:27:41 +0000 (11:27 +0000)
SOURCES/xsa139-qemuu-4.5.patch [new file with mode: 0644]
SOURCES/xsa140-qemuu-unstable-1.patch [new file with mode: 0644]
SOURCES/xsa140-qemuu-unstable-2.patch [new file with mode: 0644]
SOURCES/xsa140-qemuu-unstable-3.patch [new file with mode: 0644]
SOURCES/xsa140-qemuu-unstable-4.patch [new file with mode: 0644]
SOURCES/xsa140-qemuu-unstable-5.patch [new file with mode: 0644]
SOURCES/xsa140-qemuu-unstable-6.patch [new file with mode: 0644]
SOURCES/xsa140-qemuu-unstable-7.patch [new file with mode: 0644]
SPECS/xen.spec

diff --git a/SOURCES/xsa139-qemuu-4.5.patch b/SOURCES/xsa139-qemuu-4.5.patch
new file mode 100644 (file)
index 0000000..70ea066
--- /dev/null
@@ -0,0 +1,38 @@
+pci_piix3_xen_ide_unplug should completely unhook the unplugged
+IDEDevice from the corresponding BlockBackend, otherwise the next call
+to release_drive will try to detach the drive again.
+
+Suggested-by: Kevin Wolf <kwolf@redhat.com>
+Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+---
+ hw/ide/piix.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/hw/ide/piix.c b/hw/ide/piix.c
+index 40757eb..0524dce 100644
+--- a/hw/ide/piix.c
++++ b/hw/ide/piix.c
+@@ -172,6 +172,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
+     PCIIDEState *pci_ide;
+     DriveInfo *di;
+     int i = 0;
++    IDEDevice *idedev;
+     pci_ide = PCI_IDE(dev);
+@@ -184,6 +185,12 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
+             }
+             bdrv_close(di->bdrv);
+             pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
++            if (!(i % 2)) {
++                idedev = pci_ide->bus[di->bus].master;
++            } else {
++                idedev = pci_ide->bus[di->bus].slave;
++            }
++            idedev->conf.bs = NULL;
+             drive_put_ref(di);
+         }
+     }
+-- 
+2.1.4
+
diff --git a/SOURCES/xsa140-qemuu-unstable-1.patch b/SOURCES/xsa140-qemuu-unstable-1.patch
new file mode 100644 (file)
index 0000000..043d189
--- /dev/null
@@ -0,0 +1,82 @@
+From 5e0c290415b9d57077a86e70c8e6a058868334d3 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 15 Jul 2015 18:16:58 +0100
+Subject: [PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing
+
+Transmit offload needs to parse packet headers.  If header fields have
+unexpected values the offload processing is skipped.
+
+The code currently uses nested ifs because there is relatively little
+input validation.  The next patches will add missing input validation
+and a goto label is more appropriate to avoid deep if statement nesting.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/net/rtl8139.c | 41 ++++++++++++++++++++++-------------------
+ 1 file changed, 22 insertions(+), 19 deletions(-)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index 5f0197c..91ba33b 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2174,28 +2174,30 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+             size_t   eth_payload_len  = 0;
+             int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
+-            if (proto == ETH_P_IP)
++            if (proto != ETH_P_IP)
+             {
+-                DPRINTF("+++ C+ mode has IP packet\n");
+-
+-                /* not aligned */
+-                eth_payload_data = saved_buffer + ETH_HLEN;
+-                eth_payload_len  = saved_size   - ETH_HLEN;
+-
+-                ip = (ip_header*)eth_payload_data;
+-
+-                if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
+-                    DPRINTF("+++ C+ mode packet has bad IP version %d "
+-                        "expected %d\n", IP_HEADER_VERSION(ip),
+-                        IP_HEADER_VERSION_4);
+-                    ip = NULL;
+-                } else {
+-                    hlen = IP_HEADER_LENGTH(ip);
+-                    ip_protocol = ip->ip_p;
+-                    ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
+-                }
++                goto skip_offload;
+             }
++            DPRINTF("+++ C+ mode has IP packet\n");
++
++            /* not aligned */
++            eth_payload_data = saved_buffer + ETH_HLEN;
++            eth_payload_len  = saved_size   - ETH_HLEN;
++
++            ip = (ip_header*)eth_payload_data;
++
++            if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
++                DPRINTF("+++ C+ mode packet has bad IP version %d "
++                    "expected %d\n", IP_HEADER_VERSION(ip),
++                    IP_HEADER_VERSION_4);
++                goto skip_offload;
++            }
++
++            hlen = IP_HEADER_LENGTH(ip);
++            ip_protocol = ip->ip_p;
++            ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
++
+             if (ip)
+             {
+                 if (txdw0 & CP_TX_IPCS)
+@@ -2391,6 +2393,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+             }
+         }
++skip_offload:
+         /* update tally counter */
+         ++s->tally_counters.TxOk;
+-- 
+2.1.4
+
diff --git a/SOURCES/xsa140-qemuu-unstable-2.patch b/SOURCES/xsa140-qemuu-unstable-2.patch
new file mode 100644 (file)
index 0000000..7a76a8a
--- /dev/null
@@ -0,0 +1,373 @@
+From 2d7d80e8dc160904fa7276cc05da26c062a50066 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 15 Jul 2015 18:16:59 +0100
+Subject: [PATCH 2/7] rtl8139: drop tautologous if (ip) {...} statement
+
+The previous patch stopped using the ip pointer as an indicator that the
+IP header is present.  When we reach the if (ip) {...} statement we know
+ip is always non-NULL.
+
+Remove the if statement to reduce nesting.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/net/rtl8139.c | 305 +++++++++++++++++++++++++++----------------------------
+ 1 file changed, 151 insertions(+), 154 deletions(-)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index 91ba33b..2f12d42 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2198,198 +2198,195 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+             ip_protocol = ip->ip_p;
+             ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
+-            if (ip)
++            if (txdw0 & CP_TX_IPCS)
+             {
+-                if (txdw0 & CP_TX_IPCS)
+-                {
+-                    DPRINTF("+++ C+ mode need IP checksum\n");
++                DPRINTF("+++ C+ mode need IP checksum\n");
+-                    if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
+-                        /* bad packet header len */
+-                        /* or packet too short */
+-                    }
+-                    else
+-                    {
+-                        ip->ip_sum = 0;
+-                        ip->ip_sum = ip_checksum(ip, hlen);
+-                        DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
+-                            hlen, ip->ip_sum);
+-                    }
++                if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
++                    /* bad packet header len */
++                    /* or packet too short */
+                 }
+-
+-                if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
++                else
+                 {
+-                    int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
++                    ip->ip_sum = 0;
++                    ip->ip_sum = ip_checksum(ip, hlen);
++                    DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
++                        hlen, ip->ip_sum);
++                }
++            }
+-                    DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
+-                        "frame data %d specified MSS=%d\n", ETH_MTU,
+-                        ip_data_len, saved_size - ETH_HLEN, large_send_mss);
++            if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
++            {
++                int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
+-                    int tcp_send_offset = 0;
+-                    int send_count = 0;
++                DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
++                    "frame data %d specified MSS=%d\n", ETH_MTU,
++                    ip_data_len, saved_size - ETH_HLEN, large_send_mss);
+-                    /* maximum IP header length is 60 bytes */
+-                    uint8_t saved_ip_header[60];
++                int tcp_send_offset = 0;
++                int send_count = 0;
+-                    /* save IP header template; data area is used in tcp checksum calculation */
+-                    memcpy(saved_ip_header, eth_payload_data, hlen);
++                /* maximum IP header length is 60 bytes */
++                uint8_t saved_ip_header[60];
+-                    /* a placeholder for checksum calculation routine in tcp case */
+-                    uint8_t *data_to_checksum     = eth_payload_data + hlen - 12;
+-                    //                    size_t   data_to_checksum_len = eth_payload_len  - hlen + 12;
++                /* save IP header template; data area is used in tcp checksum calculation */
++                memcpy(saved_ip_header, eth_payload_data, hlen);
+-                    /* pointer to TCP header */
+-                    tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
++                /* a placeholder for checksum calculation routine in tcp case */
++                uint8_t *data_to_checksum     = eth_payload_data + hlen - 12;
++                //                    size_t   data_to_checksum_len = eth_payload_len  - hlen + 12;
+-                    int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
++                /* pointer to TCP header */
++                tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
+-                    /* ETH_MTU = ip header len + tcp header len + payload */
+-                    int tcp_data_len = ip_data_len - tcp_hlen;
+-                    int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
++                int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
+-                    DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
+-                        "data len %d TCP chunk size %d\n", ip_data_len,
+-                        tcp_hlen, tcp_data_len, tcp_chunk_size);
++                /* ETH_MTU = ip header len + tcp header len + payload */
++                int tcp_data_len = ip_data_len - tcp_hlen;
++                int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
+-                    /* note the cycle below overwrites IP header data,
+-                       but restores it from saved_ip_header before sending packet */
++                DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
++                    "data len %d TCP chunk size %d\n", ip_data_len,
++                    tcp_hlen, tcp_data_len, tcp_chunk_size);
+-                    int is_last_frame = 0;
++                /* note the cycle below overwrites IP header data,
++                   but restores it from saved_ip_header before sending packet */
+-                    for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
+-                    {
+-                        uint16_t chunk_size = tcp_chunk_size;
+-
+-                        /* check if this is the last frame */
+-                        if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
+-                        {
+-                            is_last_frame = 1;
+-                            chunk_size = tcp_data_len - tcp_send_offset;
+-                        }
+-
+-                        DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
+-                            be32_to_cpu(p_tcp_hdr->th_seq));
+-
+-                        /* add 4 TCP pseudoheader fields */
+-                        /* copy IP source and destination fields */
+-                        memcpy(data_to_checksum, saved_ip_header + 12, 8);
+-
+-                        DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
+-                            "packet with %d bytes data\n", tcp_hlen +
+-                            chunk_size);
+-
+-                        if (tcp_send_offset)
+-                        {
+-                            memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
+-                        }
+-
+-                        /* keep PUSH and FIN flags only for the last frame */
+-                        if (!is_last_frame)
+-                        {
+-                            TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
+-                        }
+-
+-                        /* recalculate TCP checksum */
+-                        ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
+-                        p_tcpip_hdr->zeros      = 0;
+-                        p_tcpip_hdr->ip_proto   = IP_PROTO_TCP;
+-                        p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
+-
+-                        p_tcp_hdr->th_sum = 0;
+-
+-                        int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
+-                        DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
+-                            tcp_checksum);
+-
+-                        p_tcp_hdr->th_sum = tcp_checksum;
+-
+-                        /* restore IP header */
+-                        memcpy(eth_payload_data, saved_ip_header, hlen);
+-
+-                        /* set IP data length and recalculate IP checksum */
+-                        ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
+-
+-                        /* increment IP id for subsequent frames */
+-                        ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
+-
+-                        ip->ip_sum = 0;
+-                        ip->ip_sum = ip_checksum(eth_payload_data, hlen);
+-                        DPRINTF("+++ C+ mode TSO IP header len=%d "
+-                            "checksum=%04x\n", hlen, ip->ip_sum);
+-
+-                        int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
+-                        DPRINTF("+++ C+ mode TSO transferring packet size "
+-                            "%d\n", tso_send_size);
+-                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
+-                            0, (uint8_t *) dot1q_buffer);
+-
+-                        /* add transferred count to TCP sequence number */
+-                        p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
+-                        ++send_count;
+-                    }
++                int is_last_frame = 0;
+-                    /* Stop sending this frame */
+-                    saved_size = 0;
+-                }
+-                else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
++                for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
+                 {
+-                    DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
++                    uint16_t chunk_size = tcp_chunk_size;
+-                    /* maximum IP header length is 60 bytes */
+-                    uint8_t saved_ip_header[60];
+-                    memcpy(saved_ip_header, eth_payload_data, hlen);
++                    /* check if this is the last frame */
++                    if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
++                    {
++                        is_last_frame = 1;
++                        chunk_size = tcp_data_len - tcp_send_offset;
++                    }
+-                    uint8_t *data_to_checksum     = eth_payload_data + hlen - 12;
+-                    //                    size_t   data_to_checksum_len = eth_payload_len  - hlen + 12;
++                    DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
++                        be32_to_cpu(p_tcp_hdr->th_seq));
+                     /* add 4 TCP pseudoheader fields */
+                     /* copy IP source and destination fields */
+                     memcpy(data_to_checksum, saved_ip_header + 12, 8);
+-                    if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
++                    DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
++                        "packet with %d bytes data\n", tcp_hlen +
++                        chunk_size);
++
++                    if (tcp_send_offset)
+                     {
+-                        DPRINTF("+++ C+ mode calculating TCP checksum for "
+-                            "packet with %d bytes data\n", ip_data_len);
++                        memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
++                    }
+-                        ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
+-                        p_tcpip_hdr->zeros      = 0;
+-                        p_tcpip_hdr->ip_proto   = IP_PROTO_TCP;
+-                        p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
++                    /* keep PUSH and FIN flags only for the last frame */
++                    if (!is_last_frame)
++                    {
++                        TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
++                    }
+-                        tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
++                    /* recalculate TCP checksum */
++                    ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
++                    p_tcpip_hdr->zeros      = 0;
++                    p_tcpip_hdr->ip_proto   = IP_PROTO_TCP;
++                    p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
+-                        p_tcp_hdr->th_sum = 0;
++                    p_tcp_hdr->th_sum = 0;
+-                        int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
+-                        DPRINTF("+++ C+ mode TCP checksum %04x\n",
+-                            tcp_checksum);
++                    int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
++                    DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
++                        tcp_checksum);
+-                        p_tcp_hdr->th_sum = tcp_checksum;
+-                    }
+-                    else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
+-                    {
+-                        DPRINTF("+++ C+ mode calculating UDP checksum for "
+-                            "packet with %d bytes data\n", ip_data_len);
++                    p_tcp_hdr->th_sum = tcp_checksum;
+-                        ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
+-                        p_udpip_hdr->zeros      = 0;
+-                        p_udpip_hdr->ip_proto   = IP_PROTO_UDP;
+-                        p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
++                    /* restore IP header */
++                    memcpy(eth_payload_data, saved_ip_header, hlen);
+-                        udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
++                    /* set IP data length and recalculate IP checksum */
++                    ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
+-                        p_udp_hdr->uh_sum = 0;
++                    /* increment IP id for subsequent frames */
++                    ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
+-                        int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
+-                        DPRINTF("+++ C+ mode UDP checksum %04x\n",
+-                            udp_checksum);
++                    ip->ip_sum = 0;
++                    ip->ip_sum = ip_checksum(eth_payload_data, hlen);
++                    DPRINTF("+++ C+ mode TSO IP header len=%d "
++                        "checksum=%04x\n", hlen, ip->ip_sum);
+-                        p_udp_hdr->uh_sum = udp_checksum;
+-                    }
++                    int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
++                    DPRINTF("+++ C+ mode TSO transferring packet size "
++                        "%d\n", tso_send_size);
++                    rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
++                        0, (uint8_t *) dot1q_buffer);
+-                    /* restore IP header */
+-                    memcpy(eth_payload_data, saved_ip_header, hlen);
++                    /* add transferred count to TCP sequence number */
++                    p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
++                    ++send_count;
+                 }
++
++                /* Stop sending this frame */
++                saved_size = 0;
++            }
++            else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
++            {
++                DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
++
++                /* maximum IP header length is 60 bytes */
++                uint8_t saved_ip_header[60];
++                memcpy(saved_ip_header, eth_payload_data, hlen);
++
++                uint8_t *data_to_checksum     = eth_payload_data + hlen - 12;
++                //                    size_t   data_to_checksum_len = eth_payload_len  - hlen + 12;
++
++                /* add 4 TCP pseudoheader fields */
++                /* copy IP source and destination fields */
++                memcpy(data_to_checksum, saved_ip_header + 12, 8);
++
++                if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
++                {
++                    DPRINTF("+++ C+ mode calculating TCP checksum for "
++                        "packet with %d bytes data\n", ip_data_len);
++
++                    ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
++                    p_tcpip_hdr->zeros      = 0;
++                    p_tcpip_hdr->ip_proto   = IP_PROTO_TCP;
++                    p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
++
++                    tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
++
++                    p_tcp_hdr->th_sum = 0;
++
++                    int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
++                    DPRINTF("+++ C+ mode TCP checksum %04x\n",
++                        tcp_checksum);
++
++                    p_tcp_hdr->th_sum = tcp_checksum;
++                }
++                else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
++                {
++                    DPRINTF("+++ C+ mode calculating UDP checksum for "
++                        "packet with %d bytes data\n", ip_data_len);
++
++                    ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
++                    p_udpip_hdr->zeros      = 0;
++                    p_udpip_hdr->ip_proto   = IP_PROTO_UDP;
++                    p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
++
++                    udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
++
++                    p_udp_hdr->uh_sum = 0;
++
++                    int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
++                    DPRINTF("+++ C+ mode UDP checksum %04x\n",
++                        udp_checksum);
++
++                    p_udp_hdr->uh_sum = udp_checksum;
++                }
++
++                /* restore IP header */
++                memcpy(eth_payload_data, saved_ip_header, hlen);
+             }
+         }
+-- 
+2.1.4
+
diff --git a/SOURCES/xsa140-qemuu-unstable-3.patch b/SOURCES/xsa140-qemuu-unstable-3.patch
new file mode 100644 (file)
index 0000000..5676f46
--- /dev/null
@@ -0,0 +1,39 @@
+From 043d28507ef7c5fdc34866f5e3b27a72bd0cd072 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 15 Jul 2015 18:17:00 +0100
+Subject: [PATCH 3/7] rtl8139: skip offload on short Ethernet/IP header
+
+Transmit offload features access Ethernet and IP headers the packet.  If
+the packet is too short we must not attempt to access header fields:
+
+  int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
+  ...
+  eth_payload_data = saved_buffer + ETH_HLEN;
+  ...
+  ip = (ip_header*)eth_payload_data;
+  if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/net/rtl8139.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index 2f12d42..d377b6b 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2164,6 +2164,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+         {
+             DPRINTF("+++ C+ mode offloaded task checksum\n");
++            /* Large enough for Ethernet and IP headers? */
++            if (saved_size < ETH_HLEN + sizeof(ip_header)) {
++                goto skip_offload;
++            }
++
+             /* ip packet header */
+             ip_header *ip = NULL;
+             int hlen = 0;
+-- 
+2.1.4
+
diff --git a/SOURCES/xsa140-qemuu-unstable-4.patch b/SOURCES/xsa140-qemuu-unstable-4.patch
new file mode 100644 (file)
index 0000000..495d8d6
--- /dev/null
@@ -0,0 +1,53 @@
+From 5a75d242fe019d05b46ef9bc330a6892525c84a7 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 15 Jul 2015 18:17:01 +0100
+Subject: [PATCH 4/7] rtl8139: check IP Header Length field
+
+The IP Header Length field was only checked in the IP checksum case, but
+is used in other cases too.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/net/rtl8139.c | 19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index d377b6b..cd5ac05 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2200,6 +2200,10 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+             }
+             hlen = IP_HEADER_LENGTH(ip);
++            if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
++                goto skip_offload;
++            }
++
+             ip_protocol = ip->ip_p;
+             ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
+@@ -2207,17 +2211,10 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+             {
+                 DPRINTF("+++ C+ mode need IP checksum\n");
+-                if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
+-                    /* bad packet header len */
+-                    /* or packet too short */
+-                }
+-                else
+-                {
+-                    ip->ip_sum = 0;
+-                    ip->ip_sum = ip_checksum(ip, hlen);
+-                    DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
+-                        hlen, ip->ip_sum);
+-                }
++                ip->ip_sum = 0;
++                ip->ip_sum = ip_checksum(ip, hlen);
++                DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
++                    hlen, ip->ip_sum);
+             }
+             if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
+-- 
+2.1.4
+
diff --git a/SOURCES/xsa140-qemuu-unstable-5.patch b/SOURCES/xsa140-qemuu-unstable-5.patch
new file mode 100644 (file)
index 0000000..e633ea6
--- /dev/null
@@ -0,0 +1,34 @@
+From 6c79ea275d72bc1fd88bdcf1e7d231b2c9c865de Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 15 Jul 2015 18:17:02 +0100
+Subject: [PATCH 5/7] rtl8139: check IP Total Length field
+
+The IP Total Length field includes the IP header and data.  Make sure it
+is valid and does not exceed the Ethernet payload size.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/net/rtl8139.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index cd5ac05..ed2b23b 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2205,7 +2205,12 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+             }
+             ip_protocol = ip->ip_p;
+-            ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
++
++            ip_data_len = be16_to_cpu(ip->ip_len);
++            if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
++                goto skip_offload;
++            }
++            ip_data_len -= hlen;
+             if (txdw0 & CP_TX_IPCS)
+             {
+-- 
+2.1.4
+
diff --git a/SOURCES/xsa140-qemuu-unstable-6.patch b/SOURCES/xsa140-qemuu-unstable-6.patch
new file mode 100644 (file)
index 0000000..dd716a6
--- /dev/null
@@ -0,0 +1,35 @@
+From 30aa7be430e7c982e9163f3bcc745d3aa57b6aa4 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 15 Jul 2015 18:17:03 +0100
+Subject: [PATCH 6/7] rtl8139: skip offload on short TCP header
+
+TCP Large Segment Offload accesses the TCP header in the packet.  If the
+packet is too short we must not attempt to access header fields:
+
+  tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
+  int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/net/rtl8139.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index ed2b23b..c8f0df9 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2224,6 +2224,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+             if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
+             {
++                /* Large enough for the TCP header? */
++                if (ip_data_len < sizeof(tcp_header)) {
++                    goto skip_offload;
++                }
++
+                 int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
+                 DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
+-- 
+2.1.4
+
diff --git a/SOURCES/xsa140-qemuu-unstable-7.patch b/SOURCES/xsa140-qemuu-unstable-7.patch
new file mode 100644 (file)
index 0000000..4c0ad79
--- /dev/null
@@ -0,0 +1,32 @@
+From 9a084807bf6ca7c16d997a236d304111894a6539 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Wed, 15 Jul 2015 18:17:04 +0100
+Subject: [PATCH 7/7] rtl8139: check TCP Data Offset field
+
+The TCP Data Offset field contains the length of the header.  Make sure
+it is valid and does not exceed the IP data length.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+---
+ hw/net/rtl8139.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
+index c8f0df9..2df4a51 100644
+--- a/hw/net/rtl8139.c
++++ b/hw/net/rtl8139.c
+@@ -2253,6 +2253,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
+                 int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
++                /* Invalid TCP data offset? */
++                if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) {
++                    goto skip_offload;
++                }
++
+                 /* ETH_MTU = ip header len + tcp header len + payload */
+                 int tcp_data_len = ip_data_len - tcp_hlen;
+                 int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
+-- 
+2.1.4
+
index 87e6d0b73e8febc4f966916f11228dbe72a29c2a..fcb5f67e11594d14c4bcb5f9eac32d42413cbec7 100644 (file)
@@ -19,7 +19,7 @@
 Summary: Xen is a virtual machine monitor
 Name:    xen
 Version: 4.4.2
-Release: 6%{?dist}
+Release: 7%{?dist}
 Group:   Development/Libraries
 License: GPLv2+ and LGPLv2+ and BSD
 URL:     http://xen.org/
@@ -73,6 +73,14 @@ Patch2015: xsa135-qemuu-4.5-2.patch
 Patch2016: xsa138-qemuu-1.patch
 Patch2017: xsa138-qemuu-2.patch
 Patch2018: xsa138-qemuu-3.patch
+Patch2019: xsa139-qemuu-4.5.patch
+Patch2020: xsa140-qemuu-unstable-1.patch
+Patch2021: xsa140-qemuu-unstable-2.patch
+Patch2022: xsa140-qemuu-unstable-3.patch
+Patch2023: xsa140-qemuu-unstable-4.patch
+Patch2024: xsa140-qemuu-unstable-5.patch
+Patch2025: xsa140-qemuu-unstable-6.patch
+Patch2026: xsa140-qemuu-unstable-7.patch
 
 Patch3001: xsa126-qemut.patch
 Patch3002: xsa128-qemut.patch
@@ -287,6 +295,14 @@ pushd tools/qemu-xen
 %patch2016 -p1
 %patch2017 -p1
 %patch2018 -p1
+%patch2019 -p1
+%patch2020 -p1
+%patch2021 -p1
+%patch2022 -p1
+%patch2023 -p1
+%patch2024 -p1
+%patch2025 -p1
+%patch2026 -p1
 popd
 
 pushd tools/qemu-xen-traditional
@@ -814,7 +830,11 @@ rm -rf %{buildroot}
 %endif
 
 %changelog
-* Tue Jun 30 2015 George Dunlap <george.dunlap@eu.citrix.com> - 4.4.2-6.el6.centos
+* Thu Jul 30 2015 George Dunlap <george.dunlap@eu.citrix.com> - 4.4.2-7.el6.centos
+ - Import XSA-139
+ - Import XSA-140
+
+* Tue Jul 28 2015 George Dunlap <george.dunlap@eu.citrix.com> - 4.4.2-6.el6.centos
  - Gratuitous revision bump to pull \in new version of seabios
 
 * Tue Jun 30 2015 George Dunlap <george.dunlap@eu.citrix.com> - 4.4.2-5.el6.centos