mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-10-05 22:29:49 +00:00
ip6: improve length checks for extension headers
Malformed packets could cause the extension header iteration code to read from up to two bytes beyond the end of the packet's first pbuf.
This commit is contained in:
parent
7cedf7ae71
commit
9713baea55
@ -598,15 +598,9 @@ netif_found:
|
|||||||
switch (nexth) {
|
switch (nexth) {
|
||||||
case IP6_NEXTH_HOPBYHOP:
|
case IP6_NEXTH_HOPBYHOP:
|
||||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
|
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
|
||||||
/* Get next header type. */
|
/* Get and check the header length, while staying in packet bounds. */
|
||||||
nexth = *((u8_t *)p->payload);
|
if ((p->len < 8) ||
|
||||||
|
((hlen = 8 * (1 + *((u8_t *)p->payload + 1))) > p->len)) {
|
||||||
/* Get the header length. */
|
|
||||||
hlen = 8 * (1 + *((u8_t *)p->payload + 1));
|
|
||||||
ip_data.current_ip_header_tot_len += hlen;
|
|
||||||
|
|
||||||
/* Skip over this header. */
|
|
||||||
if (hlen > p->len) {
|
|
||||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||||
("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
|
("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
|
||||||
hlen, p->len));
|
hlen, p->len));
|
||||||
@ -617,19 +611,20 @@ netif_found:
|
|||||||
goto ip6_input_cleanup;
|
goto ip6_input_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip_data.current_ip_header_tot_len += hlen;
|
||||||
|
|
||||||
|
/* Get next header type. */
|
||||||
|
nexth = *((u8_t *)p->payload);
|
||||||
|
|
||||||
|
/* Skip over this header. */
|
||||||
pbuf_header(p, -(s16_t)hlen);
|
pbuf_header(p, -(s16_t)hlen);
|
||||||
break;
|
break;
|
||||||
case IP6_NEXTH_DESTOPTS:
|
case IP6_NEXTH_DESTOPTS:
|
||||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
|
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
|
||||||
/* Get next header type. */
|
|
||||||
nexth = *((u8_t *)p->payload);
|
|
||||||
|
|
||||||
/* Get the header length. */
|
/* Get and check the header length, while staying in packet bounds. */
|
||||||
hlen = 8 * (1 + *((u8_t *)p->payload + 1));
|
if ((p->len < 8) ||
|
||||||
ip_data.current_ip_header_tot_len += hlen;
|
(hlen = 8 * (1 + *((u8_t *)p->payload + 1))) > p->len) {
|
||||||
|
|
||||||
/* Skip over this header. */
|
|
||||||
if (hlen > p->len) {
|
|
||||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||||
("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
|
("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
|
||||||
hlen, p->len));
|
hlen, p->len));
|
||||||
@ -640,19 +635,20 @@ netif_found:
|
|||||||
goto ip6_input_cleanup;
|
goto ip6_input_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip_data.current_ip_header_tot_len += hlen;
|
||||||
|
|
||||||
|
/* Get next header type. */
|
||||||
|
nexth = *((u8_t *)p->payload);
|
||||||
|
|
||||||
|
/* Skip over this header. */
|
||||||
pbuf_header(p, -(s16_t)hlen);
|
pbuf_header(p, -(s16_t)hlen);
|
||||||
break;
|
break;
|
||||||
case IP6_NEXTH_ROUTING:
|
case IP6_NEXTH_ROUTING:
|
||||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
|
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
|
||||||
/* Get next header type. */
|
|
||||||
nexth = *((u8_t *)p->payload);
|
|
||||||
|
|
||||||
/* Get the header length. */
|
/* Get and check the header length, while staying in packet bounds. */
|
||||||
hlen = 8 * (1 + *((u8_t *)p->payload + 1));
|
if ((p->len < 8) ||
|
||||||
ip_data.current_ip_header_tot_len += hlen;
|
(hlen = 8 * (1 + *((u8_t *)p->payload + 1))) > p->len) {
|
||||||
|
|
||||||
/* Skip over this header. */
|
|
||||||
if (hlen > p->len) {
|
|
||||||
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||||
("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
|
("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
|
||||||
hlen, p->len));
|
hlen, p->len));
|
||||||
@ -663,6 +659,12 @@ netif_found:
|
|||||||
goto ip6_input_cleanup;
|
goto ip6_input_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get next header type. */
|
||||||
|
nexth = *((u8_t *)p->payload);
|
||||||
|
|
||||||
|
/* Skip over this header. */
|
||||||
|
ip_data.current_ip_header_tot_len += hlen;
|
||||||
|
|
||||||
pbuf_header(p, -(s16_t)hlen);
|
pbuf_header(p, -(s16_t)hlen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -671,14 +673,8 @@ netif_found:
|
|||||||
struct ip6_frag_hdr *frag_hdr;
|
struct ip6_frag_hdr *frag_hdr;
|
||||||
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
|
LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
|
||||||
|
|
||||||
frag_hdr = (struct ip6_frag_hdr *)p->payload;
|
|
||||||
|
|
||||||
/* Get next header type. */
|
|
||||||
nexth = frag_hdr->_nexth;
|
|
||||||
|
|
||||||
/* Fragment Header length. */
|
/* Fragment Header length. */
|
||||||
hlen = 8;
|
hlen = 8;
|
||||||
ip_data.current_ip_header_tot_len += hlen;
|
|
||||||
|
|
||||||
/* Make sure this header fits in current pbuf. */
|
/* Make sure this header fits in current pbuf. */
|
||||||
if (hlen > p->len) {
|
if (hlen > p->len) {
|
||||||
@ -692,6 +688,13 @@ netif_found:
|
|||||||
goto ip6_input_cleanup;
|
goto ip6_input_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip_data.current_ip_header_tot_len += hlen;
|
||||||
|
|
||||||
|
frag_hdr = (struct ip6_frag_hdr *)p->payload;
|
||||||
|
|
||||||
|
/* Get next header type. */
|
||||||
|
nexth = frag_hdr->_nexth;
|
||||||
|
|
||||||
/* Offset == 0 and more_fragments == 0? */
|
/* Offset == 0 and more_fragments == 0? */
|
||||||
if ((frag_hdr->_fragment_offset &
|
if ((frag_hdr->_fragment_offset &
|
||||||
PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
|
PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user