udp/raw: prevent packet length overflows

Previously, on netifs with unrestricted MTUs (typically loopback
interfaces), it was possible to give a packet to the UDP/RAW API
calls that is so large that when prepending headers, the pbuf's
tot_len field would overflow. This could easily result in
undesirable behavior at lower layers, e.g. a crash when copying
the packet for later delivery.

This patch models such overflows as memory allocation errors, thus
resulting in clean failures. Checks have to be added in multiple
places to cover (hopefully) all cases.
This commit is contained in:
David van Moolenbroek 2017-01-05 18:13:41 +00:00 committed by sg
parent fffd61c746
commit 03f47e58a3
3 changed files with 12 additions and 0 deletions

View File

@ -583,6 +583,10 @@ pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
} else {
increment_magnitude = (u16_t)header_size_increment;
/* Do not allow tot_len to wrap as a result. */
if ((u16_t)(increment_magnitude + p->tot_len) < increment_magnitude) {
return 1;
}
#if 0
/* Can't assert these as some callers speculatively call
pbuf_header() to see if it's OK. Will return 1 below instead. */

View File

@ -403,6 +403,10 @@ raw_sendto_if_src(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
return err;
}
/* packet too large to add an IP header without causing an overflow? */
if ((u16_t)(p->tot_len + header_size) < p->tot_len) {
return ERR_MEM;
}
/* not enough space to add an IP header to first pbuf in given p chain? */
if (pbuf_header(p, header_size)) {
/* allocate header in new pbuf */

View File

@ -701,6 +701,10 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
}
}
/* packet too large to add a UDP header without causing an overflow? */
if ((u16_t)(p->tot_len + UDP_HLEN) < p->tot_len) {
return ERR_MEM;
}
/* not enough space to add an UDP header to first pbuf in given p chain? */
if (pbuf_header(p, UDP_HLEN)) {
/* allocate header in a separate new pbuf */