aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2023-07-28 09:39:33 +0000
committerGordon Tetlow <gordon@FreeBSD.org>2023-09-06 17:19:11 +0000
commit0692341b263e1baa17f5bbbe1d957b7e94eb647b (patch)
tree76d7dded52f215d42d237f6068cf945237bb57fb
parent595be1fc5798d15cc4f6783516138b2bdd9490b2 (diff)
downloadsrc-0692341b263e1baa17f5bbbe1d957b7e94eb647b.tar.gz
src-0692341b263e1baa17f5bbbe1d957b7e94eb647b.zip
pf: handle multiple IPv6 fragment headers
With 'scrub fragment reassemble' if a packet contains multiple IPv6 fragment headers we would reassemble the packet and immediately continue processing it. That is, we'd remove the first fragment header and expect the next header to be a final header (i.e. TCP, UDP, ICMPv6, ...). However, if it's another fragment header we'd not treat the packet correctly. That is, we'd fail to recognise the payload and treat it as if it were an IPv6 fragment rather than as its actual payload. Fix this by restarting the normalisation on the reassembled packet. If there are multiple fragment headers drop the packet. Reported by: Enrico Bassetti bassetti@di.uniroma1.it (NetSecurityLab @ Sapienza University of Rome) Approved by: so Security: FreeBSD-SA-23:10.pf Security: CVE-2023-4809 Sponsored by: Rubicon Communications, LLC ("Netgate") (cherry picked from commit 76afcbb52492f9b3e72ee7d4c4ed0a54c25e1c48) (cherry picked from commit 8922b9ac0b48749be42689ea959e6a1664f96b12)
-rw-r--r--sys/netpfil/pf/pf_norm.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index ec063f82c1d9..9e936bcd1da5 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -1213,6 +1213,8 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kkif *kif,
if (sizeof(struct ip6_hdr) + IPV6_MAXPACKET < m->m_pkthdr.len)
goto drop;
+again:
+ h = mtod(m, struct ip6_hdr *);
extoff = 0;
off = sizeof(struct ip6_hdr);
proto = h->ip6_nxt;
@@ -1303,6 +1305,8 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kkif *kif,
return (PF_PASS);
fragment:
+ if (pd->flags & PFDESC_IP_REAS)
+ return (PF_DROP);
/* Jumbo payload packets cannot be fragmented. */
plen = ntohs(h->ip6_plen);
if (plen == 0 || jumbolen)
@@ -1324,7 +1328,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kkif *kif,
return (PF_DROP);
pd->flags |= PFDESC_IP_REAS;
- return (PF_PASS);
+ goto again;
shortpkt:
REASON_SET(reason, PFRES_SHORT);