mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-27 03:51:57 -06:00
Pull request
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJVv1m5AAoJEJykq7OBq3PIO+QIAMbPSu/ZqfdANX+H4bgshudw 9CMYsgEqlmjOSeFP1Pp7lYbuceInsvY4Ks+GtWsPkV/mhEl4+g1h9uWKMSWg0jsU 14hfi7ibJomFngRPkEhcDemu6JSLAGsqedLPyrFZZyGzVZnY/TmpwG3s9CiSUSU0 h7knQLxt8QemsPU+rlH6xE/QkSdyWpERsUCTpcKufIGwIZJDeUfW1/9UxDp6M0QK LZj+8ZJzF2g/s51xHCTmAyvFZxROceEgUbGyWYNh1Aj55LMT7k+t4TTEYkizqTYj n0AUDzV65Pm67OWRf22siqb74BPt72gf/048LmhqE7o4NZvLqJ7Kff6pFDYOF0Q= =9hkg -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/rtl8139-cplus-tx-input-validation-pull-request' into staging Pull request # gpg: Signature made Mon Aug 3 13:08:25 2015 BST using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" * remotes/stefanha/tags/rtl8139-cplus-tx-input-validation-pull-request: rtl8139: check TCP Data Offset field (CVE-2015-5165) rtl8139: skip offload on short TCP header (CVE-2015-5165) rtl8139: check IP Total Length field (CVE-2015-5165) rtl8139: check IP Header Length field (CVE-2015-5165) rtl8139: skip offload on short Ethernet/IP header (CVE-2015-5165) rtl8139: drop tautologous if (ip) {...} statement (CVE-2015-5165) rtl8139: avoid nested ifs in IP header parsing (CVE-2015-5165) Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
2a3612ccc1
1 changed files with 206 additions and 189 deletions
|
@ -2150,6 +2150,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
||||||
{
|
{
|
||||||
DPRINTF("+++ C+ mode offloaded task checksum\n");
|
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 packet header */
|
||||||
ip_header *ip = NULL;
|
ip_header *ip = NULL;
|
||||||
int hlen = 0;
|
int hlen = 0;
|
||||||
|
@ -2160,8 +2165,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
||||||
size_t eth_payload_len = 0;
|
size_t eth_payload_len = 0;
|
||||||
|
|
||||||
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
|
||||||
if (proto == ETH_P_IP)
|
if (proto != ETH_P_IP)
|
||||||
{
|
{
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF("+++ C+ mode has IP packet\n");
|
DPRINTF("+++ C+ mode has IP packet\n");
|
||||||
|
|
||||||
/* not aligned */
|
/* not aligned */
|
||||||
|
@ -2174,35 +2182,39 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
||||||
DPRINTF("+++ C+ mode packet has bad IP version %d "
|
DPRINTF("+++ C+ mode packet has bad IP version %d "
|
||||||
"expected %d\n", IP_HEADER_VERSION(ip),
|
"expected %d\n", IP_HEADER_VERSION(ip),
|
||||||
IP_HEADER_VERSION_4);
|
IP_HEADER_VERSION_4);
|
||||||
ip = NULL;
|
goto skip_offload;
|
||||||
} else {
|
|
||||||
hlen = IP_HEADER_LENGTH(ip);
|
|
||||||
ip_protocol = ip->ip_p;
|
|
||||||
ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip)
|
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);
|
||||||
|
if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
|
||||||
|
goto skip_offload;
|
||||||
|
}
|
||||||
|
ip_data_len -= hlen;
|
||||||
|
|
||||||
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 = 0;
|
||||||
ip->ip_sum = ip_checksum(ip, hlen);
|
ip->ip_sum = ip_checksum(ip, hlen);
|
||||||
DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
|
||||||
hlen, ip->ip_sum);
|
hlen, ip->ip_sum);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
|
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;
|
int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
|
||||||
|
|
||||||
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
|
||||||
|
@ -2227,6 +2239,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
||||||
|
|
||||||
int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
|
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 */
|
/* ETH_MTU = ip header len + tcp header len + payload */
|
||||||
int tcp_data_len = ip_data_len - tcp_hlen;
|
int tcp_data_len = ip_data_len - tcp_hlen;
|
||||||
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
|
||||||
|
@ -2375,8 +2392,8 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
||||||
memcpy(eth_payload_data, saved_ip_header, hlen);
|
memcpy(eth_payload_data, saved_ip_header, hlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
skip_offload:
|
||||||
/* update tally counter */
|
/* update tally counter */
|
||||||
++s->tally_counters.TxOk;
|
++s->tally_counters.TxOk;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue