aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2015-10-06 12:41:29 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2015-10-07 07:35:37 +0000
commit5804c8a40450c4af7e6a02403aa7ff9133867d22 (patch)
tree6143f90d66a71b7bdfdea31eb0a6e00ad6e861dd
parent3d8174d3ef837848a2de5f0a2e8be9add7bb0acc (diff)
downloadaports-5804c8a40450c4af7e6a02403aa7ff9133867d22.tar.bz2
aports-5804c8a40450c4af7e6a02403aa7ff9133867d22.tar.xz
main/qemu: various security fixes
-rw-r--r--main/qemu/APKBUILD42
-rw-r--r--main/qemu/CVE-2015-5165.1.patch82
-rw-r--r--main/qemu/CVE-2015-5165.2.patch373
-rw-r--r--main/qemu/CVE-2015-5165.3.patch39
-rw-r--r--main/qemu/CVE-2015-5165.4.patch53
-rw-r--r--main/qemu/CVE-2015-5165.5.patch34
-rw-r--r--main/qemu/CVE-2015-5165.6.patch35
-rw-r--r--main/qemu/CVE-2015-5165.7.patch32
-rw-r--r--main/qemu/CVE-2015-5278.patch36
-rw-r--r--main/qemu/CVE-2015-5279.patch71
-rw-r--r--main/qemu/CVE-2015-6815.patch39
11 files changed, 835 insertions, 1 deletions
diff --git a/main/qemu/APKBUILD b/main/qemu/APKBUILD
index 2eeea917ef..6dc226fa0e 100644
--- a/main/qemu/APKBUILD
+++ b/main/qemu/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=qemu
pkgver=1.6.2
-pkgrel=5
+pkgrel=6
pkgdesc="QEMU is a generic machine emulator and virtualizer"
url="http://qemu.org/"
arch="all"
@@ -84,6 +84,16 @@ source="http://wiki.qemu-project.org/download/qemu-$pkgver.tar.bz2
CVE-2014-5263.patch
CVE-2015-3456.patch
CVE-2015-4037.patch
+ CVE-2015-5165.1.patch
+ CVE-2015-5165.2.patch
+ CVE-2015-5165.3.patch
+ CVE-2015-5165.4.patch
+ CVE-2015-5165.5.patch
+ CVE-2015-5165.6.patch
+ CVE-2015-5165.7.patch
+ CVE-2015-5278.patch
+ CVE-2015-5279.patch
+ CVE-2015-6815.patch
qemu-guest-agent.confd
qemu-guest-agent.initd
@@ -249,6 +259,16 @@ c10e5d649375ca3551ac7428d545890f 0428-cirrus-don-t-overflow-CirrusVGAState-cirr
35dfdc9788a11d4e7b0f8189c20f1242 CVE-2014-5263.patch
5e8a68940c4e0267e795a6ddd144e00e CVE-2015-3456.patch
97045abdf8d0543691e52f9fdf0c8d52 CVE-2015-4037.patch
+2cb289d5071f4dd93235fb7d89e178be CVE-2015-5165.1.patch
+da48557667d23bd2cbe115735b8c3034 CVE-2015-5165.2.patch
+4a33d5a280ed5e847353a9c5e4b90184 CVE-2015-5165.3.patch
+6127b15957145fa1feeeb457573cf86f CVE-2015-5165.4.patch
+e42ef3d3840db18ae172513bf14c7dbd CVE-2015-5165.5.patch
+53b14f33b64137e37366478b76e46843 CVE-2015-5165.6.patch
+52a6193bc3371e81e3eaab4db8689d85 CVE-2015-5165.7.patch
+86a63ff69fe5b8af150cd1c082a75b43 CVE-2015-5278.patch
+3e3adef433cd25e650815b0506c2c73b CVE-2015-5279.patch
+a5bf6747adf6b50bdd5ef8dc540a475c CVE-2015-6815.patch
1663bc6977f6886a58394155b1bf3676 qemu-guest-agent.confd
2035cd781ea810e94bda250c609d8d90 qemu-guest-agent.initd
66660f143235201249dc0648b39b86ee 80-kvm.rules"
@@ -263,6 +283,16 @@ e07581b81a364d5c774f30331b5d9f79e7cbdbecbece21af12ba1674d4f75084 CVE-2014-0150.
394c3eb1a880b1190676e96195987da46bc95d671a7547f226ec81147164035f CVE-2014-5263.patch
de69a47daf292fd0cc01c925a23c9fadbac0fb60c322bf89260cccceb47ca204 CVE-2015-3456.patch
6bb3f4bb71716bdde8ff417b76ceb4cee336ae93a65b2ae1db15406f382c0299 CVE-2015-4037.patch
+12d0dc1a31449288ed5e562a1e9415c437b7a2799e8afa0b251e3957a0d8ab23 CVE-2015-5165.1.patch
+c91a60b7d7e18ea95b31eca0ba940d53c14730fae1e50802375c9e5ab7d0f109 CVE-2015-5165.2.patch
+99062a9cbf4b96de8f0aa8555291cf6e296a9dbdf22ad4e9285912ba02de9261 CVE-2015-5165.3.patch
+82d2214a0bd42b03b72b26170e4c80699d74bc691b6e223780a693ad2e9c267a CVE-2015-5165.4.patch
+b728ae69e4a1d838bb1b4c5e6135e84fe8f6fc7e97fdc99915e7fc908edb4fd2 CVE-2015-5165.5.patch
+6fb23646e05ef9a4b010d2a2c0235b6ee58a293f39ed40b6b1611115c948a79a CVE-2015-5165.6.patch
+ebcadb69110ea4672795b52472222ed1ffe67a83e37c5b7d401530f43137c587 CVE-2015-5165.7.patch
+0ceeaeec1ed46bff0a1a6580d9744ff3615eae55689cd3254ec7d187758b7758 CVE-2015-5278.patch
+39ebcd2f3690e241354f9c06716e3f88966baee65907da425c4dc90006281390 CVE-2015-5279.patch
+2a67392d648c3e0b5e65eb7c51bc0ab1a3040cdbc4decb3daef391472b3b13e1 CVE-2015-6815.patch
d84e53a94584f37f3bd1b21f44077b5de0d07094c6729f26ae20ab1f7b9cc298 qemu-guest-agent.confd
982fa8ba67c728405305e4cf5a36a41a780b3d1f388ebd6377e7964c271a1c92 qemu-guest-agent.initd
37f666f1cdb7d8a62171de69b531681dcb0fba74236729dac8b6c019232eba84 80-kvm.rules"
@@ -277,6 +307,16 @@ b151de5c8e6e3f6c3015724d4717e0342cfa70f67c4979d466a5bee6e726935880fca8f25a5ee622
33c77ad81c52b91c0db6a73b29b173bf50ec05b95882e7141410e27f601af3ce41958b73ea753909e96e51f51c83d61700a799db085c23ee45db04d1779e6bdf CVE-2014-5263.patch
81485e26e30314b075a154cbce841fa3b803b70d8539a5ce00e57ec2020ab801d88c35631805811d003505dfd1909a5b70307fdbd8a192986f53143669465bd8 CVE-2015-3456.patch
8dc68c2f511a28b0c1896b89922fab8e31dea4eefe18a69e6c068dd799cfc5a5a8b2ed8c3f5d17584932ddb9a2bf72d72fdaaf19c2129babf9a8e8f4ce150659 CVE-2015-4037.patch
+1df1ff1044542c4a0b040cb7fe5bbe002ee95782277f50f2bea86fbb34d4c5404a6c1f467a4cc224020882fe8c2f113e6b44d762129bd79ae04e139494a90ddc CVE-2015-5165.1.patch
+eb332382898e0450bc6a6297e5977579a05f7b2ad304659aff37a7eed040b28013a982cdff2a1d669e968cea2aefef183081db1f6f9ae2baf64865ef2dbfa283 CVE-2015-5165.2.patch
+664ce64538441b0eeb93d1b5642acf3a1bd8c9c8b4cb5578d49e8226b967c9bef816caee41a429365ff0c5f982991f25483fc14db6c0a27d14626febaf8f8bcd CVE-2015-5165.3.patch
+a7dba1a26f33c2a65ee84fd0d3e5606cd17f623bea0c33438247e1f8d6cd72217d02bd00c28a24f54506480b12092b7351551af5f9cdcf863157cddaa461b606 CVE-2015-5165.4.patch
+7476649c099b363632b158b691f8ec2704590ec6e671f9bb013c7ffe50e593dc7c97278b6d09b5021605071a23b528875f024f5617a019954efac9c4055f6a83 CVE-2015-5165.5.patch
+a1a38fdbc3f3cebb557ae00c3764bb268019b2c9f15731bb829b3b73a87856c5d51d65cc3ff712b28601298afb2aa82e83789bab867c8fb2816f23d515af8be7 CVE-2015-5165.6.patch
+d174df707dabbaf49fadda0db9b551abef0e4c2045287bfb78ded69c7b8e6a59333d7aa1459ac7a81c0f3f711ec225157d8dabcd63d6eed10bb5755cea608fbb CVE-2015-5165.7.patch
+62cc1f05decad3c48bf9246659c4de14862aaba6b8bbf41724ae0e0b45ef5c9e0e0ae163da0f097ba0c3b2a8dd356b3bfe4f2de8de63b22b30ad6b8364cd8cc4 CVE-2015-5278.patch
+a435101af6881993bcaf58409b167d1fbe39aa97eac6b77dc48d37f75bb902b945bb01d23931ea44b6634dbff71ff735b54bd55822393163732ef5d8ae346d64 CVE-2015-5279.patch
+b7f9c48ca74351d7553f6c9c647bdeafa73bfb71f56cb4f812b55ea99db9e7e58c30854c0a4e9ad202de9a83b694f883c9eb7cd05f80288dc87f98870b3ee541 CVE-2015-6815.patch
d90c034cae3f9097466854ed1a9f32ab4b02089fcdf7320e8f4da13b2b1ff65067233f48809911485e4431d7ec1a22448b934121bc9522a2dc489009e87e2b1f qemu-guest-agent.confd
761b4e2397569dae45ae3bb9e46e28746275297f629af9e9065525497fd26a48b65d8abcf4282727afd35309e338967acf6a1b14c3169577bdc16c1f42e618b3 qemu-guest-agent.initd
9b7a89b20fcf737832cb7b4d5dc7d8301dd88169cbe5339eda69fbb51c2e537d8cb9ec7cf37600899e734209e63410d50d0821bce97e401421db39c294d97be2 80-kvm.rules"
diff --git a/main/qemu/CVE-2015-5165.1.patch b/main/qemu/CVE-2015-5165.1.patch
new file mode 100644
index 0000000000..043d189357
--- /dev/null
+++ b/main/qemu/CVE-2015-5165.1.patch
@@ -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/main/qemu/CVE-2015-5165.2.patch b/main/qemu/CVE-2015-5165.2.patch
new file mode 100644
index 0000000000..7a76a8a40d
--- /dev/null
+++ b/main/qemu/CVE-2015-5165.2.patch
@@ -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/main/qemu/CVE-2015-5165.3.patch b/main/qemu/CVE-2015-5165.3.patch
new file mode 100644
index 0000000000..5676f46532
--- /dev/null
+++ b/main/qemu/CVE-2015-5165.3.patch
@@ -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/main/qemu/CVE-2015-5165.4.patch b/main/qemu/CVE-2015-5165.4.patch
new file mode 100644
index 0000000000..495d8d616b
--- /dev/null
+++ b/main/qemu/CVE-2015-5165.4.patch
@@ -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/main/qemu/CVE-2015-5165.5.patch b/main/qemu/CVE-2015-5165.5.patch
new file mode 100644
index 0000000000..e633ea6b2e
--- /dev/null
+++ b/main/qemu/CVE-2015-5165.5.patch
@@ -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/main/qemu/CVE-2015-5165.6.patch b/main/qemu/CVE-2015-5165.6.patch
new file mode 100644
index 0000000000..dd716a6d6d
--- /dev/null
+++ b/main/qemu/CVE-2015-5165.6.patch
@@ -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/main/qemu/CVE-2015-5165.7.patch b/main/qemu/CVE-2015-5165.7.patch
new file mode 100644
index 0000000000..4c0ad79935
--- /dev/null
+++ b/main/qemu/CVE-2015-5165.7.patch
@@ -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
+
diff --git a/main/qemu/CVE-2015-5278.patch b/main/qemu/CVE-2015-5278.patch
new file mode 100644
index 0000000000..5976775711
--- /dev/null
+++ b/main/qemu/CVE-2015-5278.patch
@@ -0,0 +1,36 @@
+From 5a1ccdfe44946e726b4c6fda8a4493b3931a68c1 Mon Sep 17 00:00:00 2001
+From: P J P <pjp@fedoraproject.org>
+Date: Tue, 15 Sep 2015 16:46:59 +0530
+Subject: [PATCH] net: avoid infinite loop when receiving packets(CVE-2015-5278)
+
+Ne2000 NIC uses ring buffer of NE2000_MEM_SIZE(49152)
+bytes to process network packets. While receiving packets
+via ne2000_receive() routine, a local 'index' variable
+could exceed the ring buffer size, leading to an infinite
+loop situation.
+
+Reported-by: Qinghao Tang <luodalongde@gmail.com>
+Signed-off-by: P J P <pjp@fedoraproject.org>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 737d2b3c41d59eb8f94ab7eb419b957938f24943)
+Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
+---
+ hw/net/ne2000.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
+index 9278571..2bdb4c9 100644
+--- a/hw/net/ne2000.c
++++ b/hw/net/ne2000.c
+@@ -256,7 +256,7 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
+ if (index <= s->stop)
+ avail = s->stop - index;
+ else
+- avail = 0;
++ break;
+ len = size;
+ if (len > avail)
+ len = avail;
+--
+1.7.0.4
+
diff --git a/main/qemu/CVE-2015-5279.patch b/main/qemu/CVE-2015-5279.patch
new file mode 100644
index 0000000000..2544d6e03b
--- /dev/null
+++ b/main/qemu/CVE-2015-5279.patch
@@ -0,0 +1,71 @@
+From 7aa2bcad0ca837dd6d4bf4fa38a80314b4a6b755 Mon Sep 17 00:00:00 2001
+From: P J P <pjp@fedoraproject.org>
+Date: Tue, 15 Sep 2015 16:40:49 +0530
+Subject: [PATCH] net: add checks to validate ring buffer pointers(CVE-2015-5279)
+
+Ne2000 NIC uses ring buffer of NE2000_MEM_SIZE(49152)
+bytes to process network packets. While receiving packets
+via ne2000_receive() routine, a local 'index' variable
+could exceed the ring buffer size, which could lead to a
+memory buffer overflow. Added other checks at initialisation.
+
+Reported-by: Qinghao Tang <luodalongde@gmail.com>
+Signed-off-by: P J P <pjp@fedoraproject.org>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+(cherry picked from commit 9bbdbc66e5765068dce76e9269dce4547afd8ad4)
+Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
+---
+ hw/net/ne2000.c | 19 +++++++++++++++----
+ 1 files changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
+index 3492db3..9278571 100644
+--- a/hw/net/ne2000.c
++++ b/hw/net/ne2000.c
+@@ -230,6 +230,9 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
+ }
+
+ index = s->curpag << 8;
++ if (index >= NE2000_PMEM_END) {
++ index = s->start;
++ }
+ /* 4 bytes for header */
+ total_len = size + 4;
+ /* address for next packet (4 bytes for CRC) */
+@@ -315,13 +318,19 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+ offset = addr | (page << 4);
+ switch(offset) {
+ case EN0_STARTPG:
+- s->start = val << 8;
++ if (val << 8 <= NE2000_PMEM_END) {
++ s->start = val << 8;
++ }
+ break;
+ case EN0_STOPPG:
+- s->stop = val << 8;
++ if (val << 8 <= NE2000_PMEM_END) {
++ s->stop = val << 8;
++ }
+ break;
+ case EN0_BOUNDARY:
+- s->boundary = val;
++ if (val << 8 < NE2000_PMEM_END) {
++ s->boundary = val;
++ }
+ break;
+ case EN0_IMR:
+ s->imr = val;
+@@ -362,7 +371,9 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+ s->phys[offset - EN1_PHYS] = val;
+ break;
+ case EN1_CURPAG:
+- s->curpag = val;
++ if (val << 8 < NE2000_PMEM_END) {
++ s->curpag = val;
++ }
+ break;
+ case EN1_MULT ... EN1_MULT + 7:
+ s->mult[offset - EN1_MULT] = val;
+--
+1.7.0.4
+
diff --git a/main/qemu/CVE-2015-6815.patch b/main/qemu/CVE-2015-6815.patch
new file mode 100644
index 0000000000..6b34bd036f
--- /dev/null
+++ b/main/qemu/CVE-2015-6815.patch
@@ -0,0 +1,39 @@
+From 3a56af1fbc17ff453f6e90fb08ce0c0e6fd0b61b Mon Sep 17 00:00:00 2001
+From: P J P <pjp@fedoraproject.org>
+Date: Fri, 4 Sep 2015 17:21:06 +0100
+Subject: [PATCH] e1000: Avoid infinite loop in processing transmit descriptor (CVE-2015-6815)
+
+While processing transmit descriptors, it could lead to an infinite
+loop if 'bytes' was to become zero; Add a check to avoid it.
+
+[The guest can force 'bytes' to 0 by setting the hdr_len and mss
+descriptor fields to 0.
+--Stefan]
+
+Signed-off-by: P J P <pjp@fedoraproject.org>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Reviewed-by: Thomas Huth <thuth@redhat.com>
+Message-id: 1441383666-6590-1-git-send-email-stefanha@redhat.com
+(cherry picked from commit b947ac2bf26479e710489739c465c8af336599e7)
+Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
+---
+ hw/net/e1000.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/hw/net/e1000.c b/hw/net/e1000.c
+index 5c6bcd0..09c9e9d 100644
+--- a/hw/net/e1000.c
++++ b/hw/net/e1000.c
+@@ -740,7 +740,8 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
+ memmove(tp->data, tp->header, tp->hdr_len);
+ tp->size = tp->hdr_len;
+ }
+- } while (split_size -= bytes);
++ split_size -= bytes;
++ } while (bytes && split_size);
+ } else if (!tp->tse && tp->cptse) {
+ // context descriptor TSE is not set, while data descriptor TSE is set
+ DBGOUT(TXERR, "TCP segmentation error\n");
+--
+1.7.0.4
+