mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-05 17:28:02 +00:00
ip4_reass: fix double-free of pbuf and wrong ip_reass_pbufcount
This was broken by commit f1072fee8a
on 07/28/17 when trying to fix bug #51595
This commit is contained in:
parent
efa90d4294
commit
0795e289eb
@ -345,7 +345,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
{
|
{
|
||||||
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev = NULL;
|
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev = NULL;
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
u16_t offset, len, clen;
|
u16_t offset, len;
|
||||||
u8_t hlen;
|
u8_t hlen;
|
||||||
struct ip_hdr *fraghdr;
|
struct ip_hdr *fraghdr;
|
||||||
int valid = 1;
|
int valid = 1;
|
||||||
@ -356,7 +356,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
hlen = IPH_HL_BYTES(fraghdr);
|
hlen = IPH_HL_BYTES(fraghdr);
|
||||||
if (hlen > len) {
|
if (hlen > len) {
|
||||||
/* invalid datagram */
|
/* invalid datagram */
|
||||||
goto freepbuf;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
}
|
}
|
||||||
len = (u16_t)(len - hlen);
|
len = (u16_t)(len - hlen);
|
||||||
offset = IPH_OFFSET_BYTES(fraghdr);
|
offset = IPH_OFFSET_BYTES(fraghdr);
|
||||||
@ -372,7 +372,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
iprh->end = (u16_t)(offset + len);
|
iprh->end = (u16_t)(offset + len);
|
||||||
if (iprh->end < offset) {
|
if (iprh->end < offset) {
|
||||||
/* u16_t overflow, cannot handle this */
|
/* u16_t overflow, cannot handle this */
|
||||||
goto freepbuf;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate through until we either get to the end of the list (append),
|
/* Iterate through until we either get to the end of the list (append),
|
||||||
@ -387,7 +387,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
#if IP_REASS_CHECK_OVERLAP
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
|
if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
|
||||||
/* fragment overlaps with previous or following, throw away */
|
/* fragment overlaps with previous or following, throw away */
|
||||||
goto freepbuf;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
}
|
}
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
iprh_prev->next_pbuf = new_p;
|
iprh_prev->next_pbuf = new_p;
|
||||||
@ -400,7 +400,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
#if IP_REASS_CHECK_OVERLAP
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
if (iprh->end > iprh_tmp->start) {
|
if (iprh->end > iprh_tmp->start) {
|
||||||
/* fragment overlaps with following, throw away */
|
/* fragment overlaps with following, throw away */
|
||||||
goto freepbuf;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
}
|
}
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
/* fragment with the lowest offset */
|
/* fragment with the lowest offset */
|
||||||
@ -409,11 +409,11 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
break;
|
break;
|
||||||
} else if (iprh->start == iprh_tmp->start) {
|
} else if (iprh->start == iprh_tmp->start) {
|
||||||
/* received the same datagram twice: no need to keep the datagram */
|
/* received the same datagram twice: no need to keep the datagram */
|
||||||
goto freepbuf;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
#if IP_REASS_CHECK_OVERLAP
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
} else if (iprh->start < iprh_tmp->end) {
|
} else if (iprh->start < iprh_tmp->end) {
|
||||||
/* overlap: no need to keep the new datagram */
|
/* overlap: no need to keep the new datagram */
|
||||||
goto freepbuf;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
} else {
|
} else {
|
||||||
/* Check if the fragments received so far have no holes. */
|
/* Check if the fragments received so far have no holes. */
|
||||||
@ -491,12 +491,6 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
}
|
}
|
||||||
/* If we come here, not all fragments were received, yet! */
|
/* If we come here, not all fragments were received, yet! */
|
||||||
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
|
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
|
||||||
freepbuf:
|
|
||||||
clen = pbuf_clen(new_p);
|
|
||||||
LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= clen);
|
|
||||||
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount - clen);
|
|
||||||
pbuf_free(new_p);
|
|
||||||
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user