The branch releng/14.1 has been updated by markj:

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

commit fb925cf0a4b38bffc4c9733bae3212f07a481931
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2024-08-12 14:07:35 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2024-09-19 12:54:47 +0000

    pf: fix icmp-in-icmp state lookup
    
    In 534ee17e6 pf state checking for ICMP(v6) was made stricter. This change
    failed to correctly set the pf_pdesc for ICMP-in-ICMP lookups, resulting in 
ICMP
    error packets potentially being dropped incorrectly.
    Specially, it copied the ICMP header into a separate variable, not into the
    pf_pdesc.
    
    Populate the required pf_pdesc fields for the embedded ICMP packet's state 
lookup.
    
    Approved by:    so
    Security:       FreeBSD-EN-24:16.pf
    PR:             280701
    MFC after:      1 week
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    
    (cherry picked from commit 2da98eef1f352c496ffd458b4c68ddee972bb903)
    (cherry picked from commit 27a1a56b0d2e6ffa6ab1de69ef84fe66b7fd41e0)
---
 sys/netpfil/pf/pf.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 1cc85edfe3dc..edfa7a450054 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -7076,9 +7076,9 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                }
 #ifdef INET
                case IPPROTO_ICMP: {
-                       struct icmp             iih;
+                       struct icmp     *iih = &pd2.hdr.icmp;
 
-                       if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
+                       if (!pf_pull_hdr(m, off2, iih, ICMP_MINLEN,
                            NULL, reason, pd2.af)) {
                                DPFPRINTF(PF_DEBUG_MISC,
                                    ("pf: ICMP error message too short i"
@@ -7086,12 +7086,13 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                                return (PF_DROP);
                        }
 
-                       icmpid = iih.icmp_id;
-                       pf_icmp_mapping(&pd2, iih.icmp_type,
+                       icmpid = iih->icmp_id;
+                       pf_icmp_mapping(&pd2, iih->icmp_type,
                            &icmp_dir, &multi, &virtual_id, &virtual_type);
 
+                       pd2.dir = icmp_dir;
                        ret = pf_icmp_state_lookup(&key, &pd2, state, m,
-                           pd->dir, kif, virtual_id, virtual_type,
+                           pd2.dir, kif, virtual_id, virtual_type,
                            icmp_dir, &iidx, PF_ICMP_MULTI_NONE);
                        if (ret >= 0)
                                return (ret);
@@ -7105,10 +7106,10 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                                if (PF_ANEQ(pd2.src,
                                    &nk->addr[pd2.sidx], pd2.af) ||
                                    (virtual_type == htons(ICMP_ECHO) &&
-                                   nk->port[iidx] != iih.icmp_id))
+                                   nk->port[iidx] != iih->icmp_id))
                                        pf_change_icmp(pd2.src,
                                            (virtual_type == htons(ICMP_ECHO)) ?
-                                           &iih.icmp_id : NULL,
+                                           &iih->icmp_id : NULL,
                                            daddr, &nk->addr[pd2.sidx],
                                            (virtual_type == htons(ICMP_ECHO)) ?
                                            nk->port[iidx] : 0, NULL,
@@ -7124,7 +7125,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
 
                                m_copyback(m, off, ICMP_MINLEN, 
(caddr_t)&pd->hdr.icmp);
                                m_copyback(m, ipoff2, sizeof(h2), (caddr_t)&h2);
-                               m_copyback(m, off2, ICMP_MINLEN, (caddr_t)&iih);
+                               m_copyback(m, off2, ICMP_MINLEN, (caddr_t)iih);
                        }
                        return (PF_PASS);
                        break;
@@ -7132,9 +7133,9 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
 #endif /* INET */
 #ifdef INET6
                case IPPROTO_ICMPV6: {
-                       struct icmp6_hdr        iih;
+                       struct icmp6_hdr        *iih = &pd2.hdr.icmp6;
 
-                       if (!pf_pull_hdr(m, off2, &iih,
+                       if (!pf_pull_hdr(m, off2, iih,
                            sizeof(struct icmp6_hdr), NULL, reason, pd2.af)) {
                                DPFPRINTF(PF_DEBUG_MISC,
                                    ("pf: ICMP error message too short "
@@ -7142,8 +7143,10 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                                return (PF_DROP);
                        }
 
-                       pf_icmp_mapping(&pd2, iih.icmp6_type,
+                       pf_icmp_mapping(&pd2, iih->icmp6_type,
                            &icmp_dir, &multi, &virtual_id, &virtual_type);
+
+                       pd2.dir = icmp_dir;
                        ret = pf_icmp_state_lookup(&key, &pd2, state, m,
                            pd->dir, kif, virtual_id, virtual_type,
                            icmp_dir, &iidx, PF_ICMP_MULTI_NONE);
@@ -7171,10 +7174,10 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                                if (PF_ANEQ(pd2.src,
                                    &nk->addr[pd2.sidx], pd2.af) ||
                                    ((virtual_type == 
htons(ICMP6_ECHO_REQUEST)) &&
-                                   nk->port[pd2.sidx] != iih.icmp6_id))
+                                   nk->port[pd2.sidx] != iih->icmp6_id))
                                        pf_change_icmp(pd2.src,
                                            (virtual_type == 
htons(ICMP6_ECHO_REQUEST))
-                                           ? &iih.icmp6_id : NULL,
+                                           ? &iih->icmp6_id : NULL,
                                            daddr, &nk->addr[pd2.sidx],
                                            (virtual_type == 
htons(ICMP6_ECHO_REQUEST))
                                            ? nk->port[iidx] : 0, NULL,
@@ -7192,7 +7195,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                                    (caddr_t)&pd->hdr.icmp6);
                                m_copyback(m, ipoff2, sizeof(h2_6), 
(caddr_t)&h2_6);
                                m_copyback(m, off2, sizeof(struct icmp6_hdr),
-                                   (caddr_t)&iih);
+                                   (caddr_t)iih);
                        }
                        return (PF_PASS);
                        break;

Reply via email to