mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2025-08-03 21:14:40 +08:00
ip4_frag/ip6_frag: fix potential NULL-pointer access on memory errors
This commit is contained in:
parent
92522e4538
commit
56b29f8bcf
@ -6,6 +6,11 @@ HISTORY
|
|||||||
|
|
||||||
* [Enter new changes just after this line - do not remove this line]
|
* [Enter new changes just after this line - do not remove this line]
|
||||||
|
|
||||||
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2025-06-03: Simon Goldschmidt
|
||||||
|
* ip4_frag/ip6_frag: fix potential NULL-pointer access on memory errors
|
||||||
|
|
||||||
(STABLE-2.2.1):
|
(STABLE-2.2.1):
|
||||||
|
|
||||||
++ New features:
|
++ New features:
|
||||||
|
@ -175,19 +175,21 @@ ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *p
|
|||||||
|
|
||||||
MIB2_STATS_INC(mib2.ipreasmfails);
|
MIB2_STATS_INC(mib2.ipreasmfails);
|
||||||
#if LWIP_ICMP
|
#if LWIP_ICMP
|
||||||
iprh = (struct ip_reass_helper *)ipr->p->payload;
|
if (ipr->p != NULL) {
|
||||||
if (iprh->start == 0) {
|
iprh = (struct ip_reass_helper *)ipr->p->payload;
|
||||||
/* The first fragment was received, send ICMP time exceeded. */
|
if (iprh->start == 0) {
|
||||||
/* First, de-queue the first pbuf from r->p. */
|
/* The first fragment was received, send ICMP time exceeded. */
|
||||||
p = ipr->p;
|
/* First, de-queue the first pbuf from r->p. */
|
||||||
ipr->p = iprh->next_pbuf;
|
p = ipr->p;
|
||||||
/* Then, copy the original header into it. */
|
ipr->p = iprh->next_pbuf;
|
||||||
SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
|
/* Then, copy the original header into it. */
|
||||||
icmp_time_exceeded(p, ICMP_TE_FRAG);
|
SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
|
||||||
clen = pbuf_clen(p);
|
icmp_time_exceeded(p, ICMP_TE_FRAG);
|
||||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
clen = pbuf_clen(p);
|
||||||
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||||
pbuf_free(p);
|
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* LWIP_ICMP */
|
#endif /* LWIP_ICMP */
|
||||||
|
|
||||||
|
@ -154,35 +154,37 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr)
|
|||||||
struct ip6_reass_helper *iprh;
|
struct ip6_reass_helper *iprh;
|
||||||
|
|
||||||
#if LWIP_ICMP6
|
#if LWIP_ICMP6
|
||||||
iprh = (struct ip6_reass_helper *)ipr->p->payload;
|
if (ipr->p != NULL) {
|
||||||
if (iprh->start == 0) {
|
iprh = (struct ip6_reass_helper *)ipr->p->payload;
|
||||||
/* The first fragment was received, send ICMP time exceeded. */
|
if (iprh->start == 0) {
|
||||||
/* First, de-queue the first pbuf from r->p. */
|
/* The first fragment was received, send ICMP time exceeded. */
|
||||||
p = ipr->p;
|
/* First, de-queue the first pbuf from r->p. */
|
||||||
ipr->p = iprh->next_pbuf;
|
p = ipr->p;
|
||||||
/* Restore the part that we've overwritten with our helper structure, or we
|
ipr->p = iprh->next_pbuf;
|
||||||
* might send garbage (and disclose a pointer) in the ICMPv6 reply. */
|
/* Restore the part that we've overwritten with our helper structure, or we
|
||||||
MEMCPY(p->payload, ipr->orig_hdr, sizeof(*iprh));
|
* might send garbage (and disclose a pointer) in the ICMPv6 reply. */
|
||||||
/* Then, move back to the original ipv6 header (we are now pointing to Fragment header).
|
MEMCPY(p->payload, ipr->orig_hdr, sizeof(*iprh));
|
||||||
This cannot fail since we already checked when receiving this fragment. */
|
/* Then, move back to the original ipv6 header (we are now pointing to Fragment header).
|
||||||
if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)ipr->iphdr))) {
|
This cannot fail since we already checked when receiving this fragment. */
|
||||||
LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed", 0);
|
if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)ipr->iphdr))) {
|
||||||
|
LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Reconstruct the zoned source and destination addresses, so that we do
|
||||||
|
* not end up sending the ICMP response over the wrong link. */
|
||||||
|
ip6_addr_t src_addr, dest_addr;
|
||||||
|
ip6_addr_copy_from_packed(src_addr, IPV6_FRAG_SRC(ipr));
|
||||||
|
ip6_addr_set_zone(&src_addr, ipr->src_zone);
|
||||||
|
ip6_addr_copy_from_packed(dest_addr, IPV6_FRAG_DEST(ipr));
|
||||||
|
ip6_addr_set_zone(&dest_addr, ipr->dest_zone);
|
||||||
|
/* Send the actual ICMP response. */
|
||||||
|
icmp6_time_exceeded_with_addrs(p, ICMP6_TE_FRAG, &src_addr, &dest_addr);
|
||||||
|
}
|
||||||
|
clen = pbuf_clen(p);
|
||||||
|
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||||
|
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
||||||
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* Reconstruct the zoned source and destination addresses, so that we do
|
|
||||||
* not end up sending the ICMP response over the wrong link. */
|
|
||||||
ip6_addr_t src_addr, dest_addr;
|
|
||||||
ip6_addr_copy_from_packed(src_addr, IPV6_FRAG_SRC(ipr));
|
|
||||||
ip6_addr_set_zone(&src_addr, ipr->src_zone);
|
|
||||||
ip6_addr_copy_from_packed(dest_addr, IPV6_FRAG_DEST(ipr));
|
|
||||||
ip6_addr_set_zone(&dest_addr, ipr->dest_zone);
|
|
||||||
/* Send the actual ICMP response. */
|
|
||||||
icmp6_time_exceeded_with_addrs(p, ICMP6_TE_FRAG, &src_addr, &dest_addr);
|
|
||||||
}
|
|
||||||
clen = pbuf_clen(p);
|
|
||||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
|
||||||
pbufs_freed = (u16_t)(pbufs_freed + clen);
|
|
||||||
pbuf_free(p);
|
|
||||||
}
|
}
|
||||||
#endif /* LWIP_ICMP6 */
|
#endif /* LWIP_ICMP6 */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user