Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Jan 2025 10:38:01 GMT
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 5466aca1536e - main - pf: minor fixes for pf_walk_header6()
Message-ID:  <202501141038.50EAc1ui048459@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=5466aca1536e45b2d327ff9ae232700ea01f30e8

commit 5466aca1536e45b2d327ff9ae232700ea01f30e8
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-01-09 13:39:20 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-01-14 08:54:20 +0000

    pf: minor fixes for pf_walk_header6()
    
    - Fragment offset is in network byte order.
    - Check for legal short fragments before calling pf_pull_hdr() to
      avoid bogus reason accounting.
    - When checking wether the protocol header is within the fragment,
      count the IPv6 payload length relative to the end of the IPv6 header.
    ok henning@
    
    Obtained from:  OpenBSD, bluhm <bluhm@openbsd.org>, 3230e62590
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 11b6be239ca7..053b0b2ccb31 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -9720,9 +9720,11 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
 	struct ip6_frag		 frag;
 	struct ip6_ext		 ext;
 	struct ip6_rthdr	 rthdr;
+	uint32_t		 end;
 	int			 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 (;;) {
@@ -9746,7 +9748,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
 			}
 			pd->fragoff = pd->off;
 			/* stop walking over non initial fragments */
-			if ((frag.ip6f_offlg & IP6F_OFF_MASK) != 0)
+			if (htons((frag.ip6f_offlg & IP6F_OFF_MASK)) != 0)
 				return (PF_PASS);
 			pd->off += sizeof(frag);
 			pd->proto = frag.ip6f_nxt;
@@ -9757,14 +9759,14 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
 				REASON_SET(reason, PFRES_IPOPTIONS);
 				return (PF_DROP);
 			}
+			/* fragments may be short */
+			if (pd->fragoff != 0 && end < pd->off + sizeof(rthdr)) {
+				pd->off = pd->fragoff;
+				pd->proto = IPPROTO_FRAGMENT;
+				return (PF_PASS);
+			}
 			if (!pf_pull_hdr(pd->m, pd->off, &rthdr, sizeof(rthdr),
 			    NULL, reason, AF_INET6)) {
-				/* fragments may be short */
-				if (pd->fragoff != 0) {
-					pd->off = pd->fragoff;
-					pd->proto = IPPROTO_FRAGMENT;
-					return (PF_PASS);
-				}
 				DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short rthdr"));
 				return (PF_DROP);
 			}
@@ -9779,15 +9781,15 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
 		case IPPROTO_DSTOPTS:
 			if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext),
 			    NULL, reason, AF_INET6)) {
-				/* fragments may be short */
-				if (pd->fragoff != 0) {
-					pd->off = pd->fragoff;
-					pd->proto = IPPROTO_FRAGMENT;
-					return (PF_PASS);
-				}
 				DPFPRINTF(PF_DEBUG_MISC, ("IPv6 short exthdr"));
 				return (PF_DROP);
 			}
+			/* fragments may be short */
+			if (pd->fragoff != 0 && end < pd->off + sizeof(ext)) {
+				pd->off = pd->fragoff;
+				pd->proto = IPPROTO_FRAGMENT;
+				return (PF_PASS);
+			}
 			/* reassembly needs the ext header before the frag */
 			if (pd->fragoff == 0)
 				pd->extoff = pd->off;
@@ -9815,7 +9817,7 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
 		case IPPROTO_SCTP:
 		case IPPROTO_ICMPV6:
 			/* fragments may be short, ignore inner header then */
-			if (pd->fragoff != 0 && ntohs(h->ip6_plen) < pd->off +
+			if (pd->fragoff != 0 && end < pd->off +
 			    (pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) :
 			    pd->proto == IPPROTO_UDP ? sizeof(struct udphdr) :
 			    pd->proto == IPPROTO_SCTP ? sizeof(struct sctphdr) :



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202501141038.50EAc1ui048459>