diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2015-10-06 12:41:29 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2015-10-07 07:35:37 +0000 |
commit | 5804c8a40450c4af7e6a02403aa7ff9133867d22 (patch) | |
tree | 6143f90d66a71b7bdfdea31eb0a6e00ad6e861dd | |
parent | 3d8174d3ef837848a2de5f0a2e8be9add7bb0acc (diff) | |
download | aports-5804c8a40450c4af7e6a02403aa7ff9133867d22.tar.bz2 aports-5804c8a40450c4af7e6a02403aa7ff9133867d22.tar.xz |
main/qemu: various security fixes
-rw-r--r-- | main/qemu/APKBUILD | 42 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5165.1.patch | 82 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5165.2.patch | 373 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5165.3.patch | 39 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5165.4.patch | 53 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5165.5.patch | 34 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5165.6.patch | 35 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5165.7.patch | 32 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5278.patch | 36 | ||||
-rw-r--r-- | main/qemu/CVE-2015-5279.patch | 71 | ||||
-rw-r--r-- | main/qemu/CVE-2015-6815.patch | 39 |
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 + |