From 03f47e58a3f4c346e17e647caddc7f732a638e34 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Thu, 5 Jan 2017 18:13:41 +0000 Subject: [PATCH] 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. --- src/core/pbuf.c | 4 ++++ src/core/raw.c | 4 ++++ src/core/udp.c | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/core/pbuf.c b/src/core/pbuf.c index 4ca95b9a..edb1c952 100644 --- a/src/core/pbuf.c +++ b/src/core/pbuf.c @@ -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. */ diff --git a/src/core/raw.c b/src/core/raw.c index 29393775..2577be64 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -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 */ diff --git a/src/core/udp.c b/src/core/udp.c index 7c1c60ed..5bdb3cd1 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -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 */