Page MenuHomeFreeBSD

D31195.id92233.diff
No OneTemporary

D31195.id92233.diff

Index: sys/netinet/tcp_lro.c
===================================================================
--- sys/netinet/tcp_lro.c
+++ sys/netinet/tcp_lro.c
@@ -228,7 +228,7 @@
};
static inline void *
-tcp_lro_low_level_parser(void *ptr, struct lro_parser *parser, bool update_data, bool is_vxlan)
+tcp_lro_low_level_parser(void *ptr, struct lro_parser *parser, bool update_data, bool is_vxlan, int mlen)
{
const struct ether_vlan_header *eh;
void *old;
@@ -258,16 +258,21 @@
}
/* advance to next header */
ptr = (uint8_t *)ptr + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+ mlen -= (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
} else {
eth_type = eh->evl_encap_proto;
/* advance to next header */
+ mlen -= ETHER_HDR_LEN;
ptr = (uint8_t *)ptr + ETHER_HDR_LEN;
}
-
+ if (mlen <= 0)
+ return (NULL);
switch (eth_type) {
#ifdef INET
case htons(ETHERTYPE_IP):
parser->ip4 = ptr;
+ if (mlen < sizeof(struct ip))
+ return (NULL);
/* Ensure there are no IPv4 options. */
if ((parser->ip4->ip_hl << 2) != sizeof (*parser->ip4))
break;
@@ -275,12 +280,15 @@
if (parser->ip4->ip_off & htons(IP_MF|IP_OFFMASK))
break;
ptr = (uint8_t *)ptr + (parser->ip4->ip_hl << 2);
+ mlen -= sizeof(struct ip);
if (update_data) {
parser->data.s_addr.v4 = parser->ip4->ip_src;
parser->data.d_addr.v4 = parser->ip4->ip_dst;
}
switch (parser->ip4->ip_p) {
case IPPROTO_UDP:
+ if (mlen < sizeof(struct udphdr))
+ return (NULL);
parser->udp = ptr;
if (update_data) {
parser->data.lro_type = LRO_TYPE_IPV4_UDP;
@@ -294,6 +302,8 @@
return (ptr);
case IPPROTO_TCP:
parser->tcp = ptr;
+ if (mlen < sizeof(struct tcphdr))
+ return (NULL);
if (update_data) {
parser->data.lro_type = LRO_TYPE_IPV4_TCP;
parser->data.s_port = parser->tcp->th_sport;
@@ -301,6 +311,8 @@
} else {
MPASS(parser->data.lro_type == LRO_TYPE_IPV4_TCP);
}
+ if (mlen < (parser->tcp->th_off << 2))
+ return (NULL);
ptr = (uint8_t *)ptr + (parser->tcp->th_off << 2);
parser->total_hdr_len = (uint8_t *)ptr - (uint8_t *)old;
return (ptr);
@@ -312,13 +324,18 @@
#ifdef INET6
case htons(ETHERTYPE_IPV6):
parser->ip6 = ptr;
+ if (mlen < sizeof(struct ip6_hdr))
+ return (NULL);
ptr = (uint8_t *)ptr + sizeof(*parser->ip6);
if (update_data) {
parser->data.s_addr.v6 = parser->ip6->ip6_src;
parser->data.d_addr.v6 = parser->ip6->ip6_dst;
}
+ mlen -= sizeof(struct ip6_hdr);
switch (parser->ip6->ip6_nxt) {
case IPPROTO_UDP:
+ if (mlen < sizeof(struct udphdr))
+ return (NULL);
parser->udp = ptr;
if (update_data) {
parser->data.lro_type = LRO_TYPE_IPV6_UDP;
@@ -331,6 +348,8 @@
parser->total_hdr_len = (uint8_t *)ptr - (uint8_t *)old;
return (ptr);
case IPPROTO_TCP:
+ if (mlen < sizeof(struct tcphdr))
+ return (NULL);
parser->tcp = ptr;
if (update_data) {
parser->data.lro_type = LRO_TYPE_IPV6_TCP;
@@ -339,6 +358,8 @@
} else {
MPASS(parser->data.lro_type == LRO_TYPE_IPV6_TCP);
}
+ if (mlen < (parser->tcp->th_off << 2))
+ return (NULL);
ptr = (uint8_t *)ptr + (parser->tcp->th_off << 2);
parser->total_hdr_len = (uint8_t *)ptr - (uint8_t *)old;
return (ptr);
@@ -363,7 +384,7 @@
void *data_ptr;
/* Try to parse outer headers first. */
- data_ptr = tcp_lro_low_level_parser(m->m_data, po, update_data, false);
+ data_ptr = tcp_lro_low_level_parser(m->m_data, po, update_data, false, m->m_len);
if (data_ptr == NULL || po->total_hdr_len > m->m_len)
return (NULL);
@@ -383,7 +404,7 @@
break;
/* Try to parse inner headers. */
- data_ptr = tcp_lro_low_level_parser(data_ptr, pi, update_data, true);
+ data_ptr = tcp_lro_low_level_parser(data_ptr, pi, update_data, true, m->m_len);
if (data_ptr == NULL || pi->total_hdr_len > m->m_len)
break;

File Metadata

Mime Type
text/plain
Expires
Fri, Feb 7, 11:57 AM (18 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16510065
Default Alt Text
D31195.id92233.diff (3 KB)

Event Timeline