git: b4d2c9835c0e - main - pf: check AH header length.

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Mon, 12 Oct 2026 16:06:00 UTC
The branch main has been updated by kp:

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

commit b4d2c9835c0edfddd1d6742afa86d4873ccfad16
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2026-10-12 12:28:22 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2026-10-12 13:08:59 +0000

    pf: check AH header length.
    
    pf_walk_header() advances the packet offset for each AH extension
    header.  It was not checked that this does not exceed the packet
    length if no next header was processed.  Fix it like in IPv6.
    
    OK henning@ sashan@
    
    MFC after:      1 week
    Obtained from:  OpenBSD, bluhm <bluhm@openbsd.org>, fcd4e5522e
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 46f9f044accb..dffaabf77434 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -10825,7 +10825,7 @@ static int
 pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason)
 {
 	struct ah	 ext;
-	u_int32_t	 hlen, end;
+	u_int32_t	 hlen, end, extlen;
 	int		 hdr_cnt;
 
 	hlen = h->ip_hl << 2;
@@ -10873,7 +10873,16 @@ pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason)
 				DPFPRINTF(PF_DEBUG_MISC, "IP short exthdr");
 				return (PF_DROP);
 			}
-			pd->off += (ext.ah_len + 2) * 4;
+			extlen = (ext.ah_len + 2) * 4;
+			if (end < pd->off + extlen) {
+				if ((h->ip_off & htons(IP_MF | IP_OFFMASK))
+				    != 0)
+					return (PF_PASS);
+				DPFPRINTF(PF_DEBUG_MISC, "IP long exthdr");
+				REASON_SET(reason, PFRES_SHORT);
+				return (PF_DROP);
+			}
+			pd->off += extlen;
 			pd->proto = ext.ah_nxt;
 			break;
 		default: