ip4_reass: fix double-free of pbuf

fix mr: http://git.savannah.nongnu.org/cgit/lwip.git/commit/?id=0795e289eb2fc3460293d8d9458acdbde6db7475
This commit is contained in:
xueyunfei
2020-09-04 15:47:54 +08:00
committed by liu zhifu
parent 845bc98b2d
commit 371f9a46e6
+11 -13
View File
@@ -351,8 +351,8 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
/* Extract length and fragment offset from current fragment */
fraghdr = (struct ip_hdr*)new_p->payload;
len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
len = (u16_t)(lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4);
offset = (u16_t)((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8);
/* overwrite the fragment's ip header from the pbuf with our helper struct,
* and setup the embedded helper structure. */
@@ -362,7 +362,11 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
iprh = (struct ip_reass_helper*)new_p->payload;
iprh->next_pbuf = NULL;
iprh->start = offset;
iprh->end = offset + len;
iprh->end = (u16_t)(offset + len);
if (iprh->end < offset) {
/* u16_t overflow, cannot handle this */
return IP_REASS_VALIDATE_PBUF_DROPPED;
}
/* Iterate through until we either get to the end of the list (append),
* or we find one with a larger offset (insert). */
@@ -376,7 +380,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
#if IP_REASS_CHECK_OVERLAP
if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
/* fragment overlaps with previous or following, throw away */
goto freepbuf;
return IP_REASS_VALIDATE_PBUF_DROPPED;
}
#endif /* IP_REASS_CHECK_OVERLAP */
iprh_prev->next_pbuf = new_p;
@@ -389,7 +393,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
#if IP_REASS_CHECK_OVERLAP
if (iprh->end > iprh_tmp->start) {
/* fragment overlaps with following, throw away */
goto freepbuf;
return IP_REASS_VALIDATE_PBUF_DROPPED;
}
#endif /* IP_REASS_CHECK_OVERLAP */
/* fragment with the lowest offset */
@@ -398,11 +402,11 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
break;
} else if (iprh->start == iprh_tmp->start) {
/* received the same datagram twice: no need to keep the datagram */
goto freepbuf;
return IP_REASS_VALIDATE_PBUF_DROPPED;
#if IP_REASS_CHECK_OVERLAP
} else if (iprh->start < iprh_tmp->end) {
/* overlap: no need to keep the new datagram */
goto freepbuf;
return IP_REASS_VALIDATE_PBUF_DROPPED;
#endif /* IP_REASS_CHECK_OVERLAP */
} else {
/* Check if the fragments received so far have no holes. */
@@ -480,12 +484,6 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
}
/* If we come here, not all fragments were received, yet! */
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
#if IP_REASS_CHECK_OVERLAP
freepbuf:
ip_reass_pbufcount -= pbuf_clen(new_p);
pbuf_free(new_p);
return IP_REASS_VALIDATE_PBUF_DROPPED;
#endif /* IP_REASS_CHECK_OVERLAP */
}
/**