git: a2a0e5e0e38f - stable/15 - pf: check extension header length.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 20 Oct 2026 07:24:35 UTC
The branch stable/15 has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=a2a0e5e0e38fa9791f2966e0430b8754530d6b72
commit a2a0e5e0e38fa9791f2966e0430b8754530d6b72
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2026-10-12 12:25:07 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2026-10-20 07:22:50 +0000
pf: check extension header length.
pf_walk_header6() advances the packet offset for each IPv6 extension
header. It was not checked that this does not exceed the packet
length if no next header was processed. When used with af-to rules,
this could trigger a panic: m_copydata: null mbuf.
from Acts1631; OK henning@ sashan@
MFC after: 1 week
Obtained from: OpenBSD, bluhm <bluhm@openbsd.org>, 6d56112588
Sponsored by: Rubicon Communications, LLC ("Netgate")
(cherry picked from commit ccb19b359aae4b7e7315ad61d33d9a35d85849d1)
---
sys/netpfil/pf/pf.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 4a4dd209b7c2..ea081fa90b34 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -10232,7 +10232,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
struct ip6_ext ext;
struct icmp6_hdr icmp6;
struct ip6_rthdr rthdr;
- uint32_t end;
+ uint32_t end, extlen;
int hdr_cnt, fraghdr_cnt = 0, rthdr_cnt = 0;
pd->off += sizeof(struct ip6_hdr);
@@ -10343,9 +10343,20 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
return (PF_DROP);
}
if (pd->proto == IPPROTO_AH)
- pd->off += (ext.ip6e_len + 2) * 4;
+ extlen = (ext.ip6e_len + 2) * 4;
else
- pd->off += (ext.ip6e_len + 1) * 8;
+ extlen = (ext.ip6e_len + 1) * 8;
+ if (end < pd->off + extlen) {
+ if (pd->fragoff != 0) {
+ pd->off = pd->fragoff;
+ pd->proto = IPPROTO_FRAGMENT;
+ return (PF_PASS);
+ }
+ DPFPRINTF(PF_DEBUG_MISC, "IPv6 long exthdr");
+ REASON_SET(reason, PFRES_SHORT);
+ return (PF_DROP);
+ }
+ pd->off += extlen;
pd->proto = ext.ip6e_nxt;
break;
case IPPROTO_ICMPV6: