The branch releng/14.1 has been updated by markj:

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

commit 84b57a4c5b848d44ec0918c28d8c27bec948a151
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2024-08-14 09:29:30 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2024-09-19 12:55:09 +0000

    pf: invert direction for inner icmp state lookups
    
    (e.g. traceroute with icmp)
    ok henning, jsing
    
    Also extend the test case to cover this scenario.
    
    Approved by:    so
    Security:       FreeBSD-EN-24:16.pf
    PR:             280701
    Obtained from:  OpenBSD
    MFC after:      1 week
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    
    (cherry picked from commit 89f6723288b0d27d3f14f93e6e83f672fa2b8aca)
    (cherry picked from commit 46c4fc50d3012ca3c8756df243589add36b70830)
---
 sys/netpfil/pf/pf.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index edfa7a450054..43f32f673842 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -342,7 +342,7 @@ static int           pf_test_state_udp(struct pf_kstate **,
 int                     pf_icmp_state_lookup(struct pf_state_key_cmp *,
                            struct pf_pdesc *, struct pf_kstate **, struct mbuf 
*,
                            int, struct pfi_kkif *, u_int16_t, u_int16_t,
-                           int, int *, int);
+                           int, int *, int, int);
 static int              pf_test_state_icmp(struct pf_kstate **,
                            struct pfi_kkif *, struct mbuf *, int,
                            void *, struct pf_pdesc *, u_short *);
@@ -6582,7 +6582,8 @@ pf_multihome_scan_asconf(struct mbuf *m, int start, int 
len,
 int
 pf_icmp_state_lookup(struct pf_state_key_cmp *key, struct pf_pdesc *pd,
     struct pf_kstate **state, struct mbuf *m, int direction, struct pfi_kkif 
*kif,
-    u_int16_t icmpid, u_int16_t type, int icmp_dir, int *iidx, int multi)
+    u_int16_t icmpid, u_int16_t type, int icmp_dir, int *iidx, int multi,
+    int inner)
 {
        key->af = pd->af;
        key->proto = pd->proto;
@@ -6619,7 +6620,8 @@ pf_icmp_state_lookup(struct pf_state_key_cmp *key, struct 
pf_pdesc *pd,
 
        /* Is this ICMP message flowing in right direction? */
        if ((*state)->rule.ptr->type &&
-           (((*state)->direction == direction) ?
+           (((!inner && (*state)->direction == direction) ||
+           (inner && (*state)->direction != direction)) ?
            PF_IN : PF_OUT) != icmp_dir) {
                if (V_pf_status.debug >= PF_DEBUG_MISC) {
                        printf("pf: icmp type %d in wrong direction (%d): ",
@@ -6677,7 +6679,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                 */
                ret = pf_icmp_state_lookup(&key, pd, state, m, pd->dir,
                    kif, virtual_id, virtual_type, icmp_dir, &iidx,
-                   PF_ICMP_MULTI_NONE);
+                   PF_ICMP_MULTI_NONE, 0);
                if (ret >= 0) {
                        if (ret == PF_DROP && pd->af == AF_INET6 &&
                            icmp_dir == PF_OUT) {
@@ -6685,7 +6687,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                                        PF_STATE_UNLOCK((*state));
                                ret = pf_icmp_state_lookup(&key, pd, state, m,
                                    pd->dir, kif, virtual_id, virtual_type,
-                                   icmp_dir, &iidx, multi);
+                                   icmp_dir, &iidx, multi, 0);
                                if (ret >= 0)
                                        return (ret);
                        } else
@@ -6769,6 +6771,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                int             off2 = 0;
 
                pd2.af = pd->af;
+               pd2.dir = pd->dir;
                /* Payload packet is from the opposite direction. */
                pd2.sidx = (pd->dir == PF_IN) ? 1 : 0;
                pd2.didx = (pd->dir == PF_IN) ? 0 : 1;
@@ -7090,10 +7093,9 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                        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,
                            pd2.dir, kif, virtual_id, virtual_type,
-                           icmp_dir, &iidx, PF_ICMP_MULTI_NONE);
+                           icmp_dir, &iidx, PF_ICMP_MULTI_NONE, 1);
                        if (ret >= 0)
                                return (ret);
 
@@ -7146,10 +7148,9 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                        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);
+                           icmp_dir, &iidx, PF_ICMP_MULTI_NONE, 1);
                        if (ret >= 0) {
                                if (ret == PF_DROP && pd->af == AF_INET6 &&
                                    icmp_dir == PF_OUT) {
@@ -7158,7 +7159,7 @@ pf_test_state_icmp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                                        ret = pf_icmp_state_lookup(&key, pd,
                                            state, m, pd->dir, kif,
                                            virtual_id, virtual_type,
-                                           icmp_dir, &iidx, multi);
+                                           icmp_dir, &iidx, multi, 1);
                                        if (ret >= 0)
                                                return (ret);
                                } else

Reply via email to