[PATCH v3 5/8] ip_frag: reject oversized reassembled datagrams
From: Stephen Hemminger <stephen@networkplumber.org>
Date: 2026-07-01 16:22:08
Subsystem:
library code, the rest · Maintainers:
Andrew Morton, Linus Torvalds
The reassembled total length of a packet must not exceed 65535.
A fragment with a high offset could drive the sum past that,
causing silent truncation since IP payload_len/total_length is 16 bits.
When reassembling a packet the total length should not be allowed
to exceed 65535. A fragment with high offset could drive the sum
past that, causing silent truncation.
A valid datagram never exceeds 65535 bytes, so reject any fragment
whose resulting length would exceed that.
Fold the test into the existing zero-length check.
Fixes: cc8f4d020c0b ("examples/ip_reassembly: initial import")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Konstantin Ananyev <redacted>
---
lib/ip_frag/rte_ipv4_reassembly.c | 9 +++++++--
lib/ip_frag/rte_ipv6_reassembly.c | 9 +++++++--
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/lib/ip_frag/rte_ipv4_reassembly.c b/lib/ip_frag/rte_ipv4_reassembly.c
index 980f7a3b77..727fc58243 100644
--- a/lib/ip_frag/rte_ipv4_reassembly.c
+++ b/lib/ip_frag/rte_ipv4_reassembly.c@@ -136,8 +136,13 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); - /* check that fragment length is greater then zero. */ - if (ip_len <= 0) { + /* + * Drop fragments with no payload, and any fragment whose end would + * make the reassembled datagram exceed the maximum IPv4 size. The + * total_length field is 16 bits, so otherwise it is silently + * truncated while the mbuf still holds the full length. + */ + if (ip_len <= 0 || ip_ofs + ip_len + mb->l3_len > UINT16_MAX) { IP_FRAG_MBUF2DR(dr, mb); return NULL; }
diff --git a/lib/ip_frag/rte_ipv6_reassembly.c b/lib/ip_frag/rte_ipv6_reassembly.c
index b6f623d53b..9aa2f2d08b 100644
--- a/lib/ip_frag/rte_ipv6_reassembly.c
+++ b/lib/ip_frag/rte_ipv6_reassembly.c@@ -174,8 +174,13 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); - /* check that fragment length is greater then zero. */ - if (ip_len <= 0) { + /* + * Drop fragments with no payload, and any fragment whose end would + * make the reassembled payload exceed 65535 bytes. The payload_len + * field is 16 bits, so otherwise it is silently truncated while the + * mbuf still holds the full length. + */ + if (ip_len <= 0 || ip_ofs + ip_len > UINT16_MAX) { IP_FRAG_MBUF2DR(dr, mb); return NULL; }
--
2.53.0