diff --git a/CHANGELOG b/CHANGELOG index f9d817eb..bc3a0fad 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -202,6 +202,11 @@ HISTORY ++ Bugfixes: + 2015-02-25: Simon Goldschmidt + * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted + packets), implemented task #12357 (Ensure that malicious packets don't + assert-fail): improved some pbuf_header calls to not assert-fail. + 2015-02-25: patch by Joel Cunningham * udp.h/.c, sockets.c: fixed bug #43028 (IP_MULTICAST_TTL affects unicast datagrams) diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c index 4571ac26..6ef68354 100644 --- a/src/core/ipv4/ip4.c +++ b/src/core/ipv4/ip4.c @@ -352,6 +352,11 @@ ip_input(struct pbuf *p, struct netif *inp) /* obtain ip length in bytes */ iphdr_len = ntohs(IPH_LEN(iphdr)); + /* Trim pbuf. This is especially required for packets < 60 bytes. */ + if (iphdr_len < p->tot_len) { + pbuf_realloc(p, iphdr_len); + } + /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { if (iphdr_hlen > p->len) { @@ -387,10 +392,6 @@ ip_input(struct pbuf *p, struct netif *inp) } #endif - /* Trim pbuf. This should have been done at the netif layer, - * but we'll do it anyway just to be sure that its done. */ - pbuf_realloc(p, iphdr_len); - /* copy IP addresses to aligned ip_addr_t */ ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_dest), iphdr->dest); ip_addr_copy(*ipX_2_ip(&ip_data.current_iphdr_src), iphdr->src); diff --git a/src/netif/etharp.c b/src/netif/etharp.c index 44a19e2e..a6932521 100644 --- a/src/netif/etharp.c +++ b/src/netif/etharp.c @@ -1427,7 +1427,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) etharp_ip_input(netif, p); #endif /* ETHARP_TRUST_IP_MAC */ /* skip Ethernet header */ - if (pbuf_header(p, (s16_t)-ip_hdr_offset)) { + if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, ip_hdr_offset)); @@ -1460,7 +1460,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) #if LWIP_IPV6 case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ /* skip Ethernet header */ - if(pbuf_header(p, (s16_t)-ip_hdr_offset)) { + if((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, ip_hdr_offset));