[PATCH v2 4/8] ip_frag: drop IPv6 fragments with per-fragment headers
Stephen Hemminger
stephen at networkplumber.org
Tue Jun 30 17:36:16 CEST 2026
IPv6 reassembly assumes the fragment header directly follows the IPv6
header. ipv6_frag_reassemble() patches the next-header field and removes
the fragment header at a fixed offset, so a fragment with per-fragment
extension headers before the fragment header reassembles to a corrupt
datagram.
Drop the fragment when its fragment header does not directly follow the
IPv6 header. Headers after the fragment header are payload and are
unaffected.
RFC 8200 permits discarding packets with extension headers out of the
recommended order, and RFC 9099 recommends dropping non-conforming
fragmented packets.
Fixes: 4f1a8f633862 ("ip_frag: add IPv6 reassembly")
Cc: stable at dpdk.org
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
lib/ip_frag/rte_ipv6_reassembly.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/lib/ip_frag/rte_ipv6_reassembly.c b/lib/ip_frag/rte_ipv6_reassembly.c
index 0e809a01e5..b6f623d53b 100644
--- a/lib/ip_frag/rte_ipv6_reassembly.c
+++ b/lib/ip_frag/rte_ipv6_reassembly.c
@@ -180,6 +180,28 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
return NULL;
}
+ /*
+ * Only a fragment header directly following the IPv6 header is supported.
+ * Per-fragment (unfragmentable) extension headers placed
+ * before the fragment header are not handled: ipv6_frag_reassemble()
+ * patches the IPv6 header's next-header field and removes the fragment
+ * header assuming it sits immediately after the IPv6 header, so such a
+ * fragment would be reassembled into a corrupt datagram. Drop it.
+ *
+ * Extension headers after the fragment header (destination options,
+ * AH, ESP, upper-layer) are part of the fragmentable payload and are
+ * reassembled as opaque bytes, so they are not affected. The test uses
+ * the fragment header's position rather than l3_len so that callers
+ * which include later headers in l3_len are not rejected.
+ */
+ if ((uintptr_t)frag_hdr != (uintptr_t)(ip_hdr + 1)) {
+ IP_FRAG_LOG(DEBUG,
+ "%s:%d: drop fragment with header before frag header, offset %zu\n",
+ __func__, __LINE__, (uintptr_t)frag_hdr - (uintptr_t)ip_hdr);
+ IP_FRAG_MBUF2DR(dr, mb);
+ return NULL;
+ }
+
if (unlikely(trim > 0))
rte_pktmbuf_trim(mb, trim);
--
2.53.0
More information about the stable
mailing list