git: fb7c3f0274ff - main - pf: refactor length check in pf_pull_hdr()

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 28 May 2025 21:55:49 UTC
The branch main has been updated by kp:

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

commit fb7c3f0274ffb00f983a02251bf97089767a921c
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-05-26 08:16:20 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-05-28 21:40:36 +0000

    pf: refactor length check in pf_pull_hdr()
    
    Move the common length check in pf_pull_hdr() after the address
    family switch.  This makes the specific calculation more obvious.
    OK claudio@
    
    Obtained from:  OpenBSD, bluhm <bluhm@openbsd.org>, 9f98372a33
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index e9082da193e6..996e329a204e 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -8756,6 +8756,7 @@ void *
 pf_pull_hdr(const struct mbuf *m, int off, void *p, int len,
     u_short *actionp, u_short *reasonp, sa_family_t af)
 {
+	int iplen = 0;
 	switch (af) {
 #ifdef INET
 	case AF_INET: {
@@ -8771,12 +8772,7 @@ pf_pull_hdr(const struct mbuf *m, int off, void *p, int len,
 			}
 			return (NULL);
 		}
-		if (m->m_pkthdr.len < off + len ||
-		    ntohs(h->ip_len) < off + len) {
-			ACTION_SET(actionp, PF_DROP);
-			REASON_SET(reasonp, PFRES_SHORT);
-			return (NULL);
-		}
+		iplen = ntohs(h->ip_len);
 		break;
 	}
 #endif /* INET */
@@ -8784,17 +8780,16 @@ pf_pull_hdr(const struct mbuf *m, int off, void *p, int len,
 	case AF_INET6: {
 		const struct ip6_hdr	*h = mtod(m, struct ip6_hdr *);
 
-		if (m->m_pkthdr.len < off + len ||
-		    (ntohs(h->ip6_plen) + sizeof(struct ip6_hdr)) <
-		    (unsigned)(off + len)) {
-			ACTION_SET(actionp, PF_DROP);
-			REASON_SET(reasonp, PFRES_SHORT);
-			return (NULL);
-		}
+		iplen = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
 		break;
 	}
 #endif /* INET6 */
 	}
+	if (m->m_pkthdr.len < off + len || iplen < off + len) {
+		ACTION_SET(actionp, PF_DROP);
+		REASON_SET(reasonp, PFRES_SHORT);
+		return (NULL);
+	}
 	m_copydata(m, off, len, p);
 	return (p);
 }