git: 3bb82353b528 - main - pf: reject hop-by-hop if it's not the first extension header
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 08 May 2025 13:10:40 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=3bb82353b528e7e2a0815648d5be36c610b001f9
commit 3bb82353b528e7e2a0815648d5be36c610b001f9
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-05-06 09:18:27 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-05-08 13:10:24 +0000
pf: reject hop-by-hop if it's not the first extension header
The pf fragment reassembly code accepted IPv6 hop-by-hop headers
after fragment headers. Add an extra check that the hop-by-hop
header is always the first extension header after the IPv6 header.
Found by Antonios Atlasis; OK sthen@ mpi@
Obtained from: OpenBSD, bluhm <bluhm@openbsd.org>, 17ea4b2bcd
Sponsored by: Rubicon Communications, LLC ("Netgate")
---
sys/netpfil/pf/pf.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 2515c85c3eb7..2f69f36e2db3 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -9774,13 +9774,14 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
struct ip6_ext ext;
struct ip6_rthdr rthdr;
uint32_t end;
- int fraghdr_cnt = 0, rthdr_cnt = 0;
+ int hdr_cnt = 0, fraghdr_cnt = 0, rthdr_cnt = 0;
pd->off += sizeof(struct ip6_hdr);
end = pd->off + ntohs(h->ip6_plen);
pd->fragoff = pd->extoff = pd->jumbolen = 0;
pd->proto = h->ip6_nxt;
for (;;) {
+ hdr_cnt++;
switch (pd->proto) {
case IPPROTO_FRAGMENT:
if (fraghdr_cnt++) {
@@ -9833,8 +9834,15 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
return (PF_DROP);
}
/* FALLTHROUGH */
- case IPPROTO_AH:
case IPPROTO_HOPOPTS:
+ /* RFC2460 4.1: Hop-by-Hop only after IPv6 header */
+ if (pd->proto == IPPROTO_HOPOPTS && hdr_cnt > 1) {
+ DPFPRINTF(PF_DEBUG_MISC, ("IPv6 hopopts not first"));
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
+ }
+ /* FALLTHROUGH */
+ case IPPROTO_AH:
case IPPROTO_DSTOPTS:
if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext),
NULL, reason, AF_INET6)) {