The branch main has been updated by kp:

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

commit d10de21f2f7df59344f8611546989b36e4fd867c
Author:     Kajetan Staszkiewicz <veg...@tuxpowered.net>
AuthorDate: 2023-08-24 11:05:33 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2023-08-24 11:05:33 +0000

    pf: Access r->rpool.cur->kif under mutex protection
    
    pf_route() sends traffic to a specified next hop over a specific
    interface. The next hop is obtained in pf_map_addr() but the interface
    is obtained directly via r->rpool.cur->kif` outside of the lock held in
    pf_map_addr() in multiple places around pf. The chosen interface is not
    stored in source node.
    
    Move the interface selection into pf_map_addr(), have the function
    return it together with the chosen IP address and ensure its stored
    in struct pf_ksrc_node, store it in the source node and use the stored
    value when needed.
    
    Sponsored by:   InnoGames GmbH
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D41570
---
 sys/net/pfvar.h        |  5 +++--
 sys/netpfil/pf/pf.c    | 31 +++++++++++++++++--------------
 sys/netpfil/pf/pf_lb.c | 24 +++++++++++++++++++-----
 3 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 21ebca755b3d..f9cb45f696d3 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -873,7 +873,7 @@ struct pf_ksrc_node {
        struct pf_addr   raddr;
        struct pf_krule_slist    match_rules;
        union pf_krule_ptr rule;
-       struct pfi_kkif *kif;
+       struct pfi_kkif *rkif;
        counter_u64_t    bytes[2];
        counter_u64_t    packets[2];
        u_int32_t        states;
@@ -2474,7 +2474,8 @@ int                        
pf_step_out_of_keth_anchor(struct pf_keth_anchor_stackframe *,
 
 u_short                         pf_map_addr(u_int8_t, struct pf_krule *,
                            struct pf_addr *, struct pf_addr *,
-                           struct pf_addr *, struct pf_ksrc_node **);
+                           struct pfi_kkif **nkif, struct pf_addr *,
+                           struct pf_ksrc_node **);
 struct pf_krule                *pf_get_translation(struct pf_pdesc *, struct 
mbuf *,
                            int, struct pfi_kkif *, struct pf_ksrc_node **,
                            struct pf_state_key **, struct pf_state_key **,
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index c80553ba017d..a5d7c1ba0155 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -4880,15 +4880,14 @@ pf_create_state(struct pf_krule *r, struct pf_krule 
*nr, struct pf_krule *a,
 
        if (r->rt) {
                /* pf_map_addr increases the reason counters */
-               if ((reason = pf_map_addr(pd->af, r, pd->src, &s->rt_addr, NULL,
-                   &sn)) != 0) {
+               if ((reason = pf_map_addr(pd->af, r, pd->src, &s->rt_addr,
+                   &s->rt_kif, NULL, &sn)) != 0) {
                        pf_src_tree_remove_state(s);
                        s->timeout = PFTM_UNLINKED;
                        STATE_DEC_COUNTERS(s);
                        pf_free_state(s);
                        goto csfailed;
                }
-               s->rt_kif = r->rpool.cur->kif;
                s->rt = r->rt;
        }
 
@@ -6700,6 +6699,7 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct 
ifnet *oifp,
        struct mbuf             *m0, *m1, *md;
        struct sockaddr_in      dst;
        struct ip               *ip;
+       struct pfi_kkif         *nkif = NULL;
        struct ifnet            *ifp = NULL;
        struct pf_addr           naddr;
        struct pf_ksrc_node     *sn = NULL;
@@ -6784,21 +6784,22 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct 
ifnet *oifp,
                        goto bad_locked;
                }
                pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
-                   &naddr, NULL, &sn);
+                   &naddr, &nkif, NULL, &sn);
                if (!PF_AZERO(&naddr, AF_INET))
                        dst.sin_addr.s_addr = naddr.v4.s_addr;
-               ifp = r->rpool.cur->kif ?
-                   r->rpool.cur->kif->pfik_ifp : NULL;
+               ifp = nkif ? nkif->pfik_ifp : NULL;
        } else {
                if (!PF_AZERO(&s->rt_addr, AF_INET))
                        dst.sin_addr.s_addr =
                            s->rt_addr.v4.s_addr;
                ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
+               /* If pfsync'd */
+               if (ifp == NULL)
+                       ifp = r->rpool.cur->kif ?
+                           r->rpool.cur->kif->pfik_ifp : NULL;
                PF_STATE_UNLOCK(s);
        }
-       /* If pfsync'd */
-       if (ifp == NULL)
-               ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
+
        if (ifp == NULL)
                goto bad;
 
@@ -6913,6 +6914,7 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct 
ifnet *oifp,
        struct mbuf             *m0, *md;
        struct sockaddr_in6     dst;
        struct ip6_hdr          *ip6;
+       struct pfi_kkif         *nkif = NULL;
        struct ifnet            *ifp = NULL;
        struct pf_addr           naddr;
        struct pf_ksrc_node     *sn = NULL;
@@ -6995,24 +6997,25 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct 
ifnet *oifp,
                        goto bad_locked;
                }
                pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
-                   &naddr, NULL, &sn);
+                   &naddr, &nkif, NULL, &sn);
                if (!PF_AZERO(&naddr, AF_INET6))
                        PF_ACPY((struct pf_addr *)&dst.sin6_addr,
                            &naddr, AF_INET6);
-               ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
+               ifp = nkif ? nkif->pfik_ifp : NULL;
        } else {
                if (!PF_AZERO(&s->rt_addr, AF_INET6))
                        PF_ACPY((struct pf_addr *)&dst.sin6_addr,
                            &s->rt_addr, AF_INET6);
                ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
+               /* If pfsync'd */
+               if (ifp == NULL)
+                       ifp = r->rpool.cur->kif ?
+                           r->rpool.cur->kif->pfik_ifp : NULL;
        }
 
        if (s)
                PF_STATE_UNLOCK(s);
 
-       /* If pfsync'd */
-       if (ifp == NULL)
-               ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
        if (ifp == NULL)
                goto bad;
 
diff --git a/sys/netpfil/pf/pf_lb.c b/sys/netpfil/pf/pf_lb.c
index 09e5d6a7a97f..eb3d087e3df6 100644
--- a/sys/netpfil/pf/pf_lb.c
+++ b/sys/netpfil/pf/pf_lb.c
@@ -222,7 +222,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct 
pf_krule *r,
        struct pf_addr          init_addr;
 
        bzero(&init_addr, sizeof(init_addr));
-       if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+       if (pf_map_addr(af, r, saddr, naddr, NULL, &init_addr, sn))
                return (1);
 
        bzero(&key, sizeof(key));
@@ -299,7 +299,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct 
pf_krule *r,
                         * pick a different source address since we're out
                         * of free port choices for the current one.
                         */
-                       if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+                       if (pf_map_addr(af, r, saddr, naddr, NULL, &init_addr, 
sn))
                                return (1);
                        break;
                case PF_POOL_NONE:
@@ -350,7 +350,8 @@ pf_get_mape_sport(sa_family_t af, u_int8_t proto, struct 
pf_krule *r,
 
 u_short
 pf_map_addr(sa_family_t af, struct pf_krule *r, struct pf_addr *saddr,
-    struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_ksrc_node **sn)
+    struct pf_addr *naddr, struct pfi_kkif **nkif, struct pf_addr *init_addr,
+    struct pf_ksrc_node **sn)
 {
        u_short                  reason = 0;
        struct pf_kpool         *rpool = &r->rpool;
@@ -377,11 +378,15 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                }
 
                PF_ACPY(naddr, &(*sn)->raddr, af);
+               if (nkif)
+                       *nkif = (*sn)->rkif;
                if (V_pf_status.debug >= PF_DEBUG_NOISY) {
                        printf("pf_map_addr: src tracking maps ");
                        pf_print_host(saddr, 0, af);
                        printf(" to ");
                        pf_print_host(naddr, 0, af);
+                       if (nkif)
+                               printf("@%s", (*nkif)->pfik_name);
                        printf("\n");
                }
                goto done;
@@ -539,13 +544,22 @@ pf_map_addr(sa_family_t af, struct pf_krule *r, struct 
pf_addr *saddr,
                break;
            }
        }
-       if (*sn != NULL)
+
+       if (nkif)
+               *nkif = rpool->cur->kif;
+
+       if (*sn != NULL) {
                PF_ACPY(&(*sn)->raddr, naddr, af);
+               if (nkif)
+                       (*sn)->rkif = *nkif;
+       }
 
        if (V_pf_status.debug >= PF_DEBUG_NOISY &&
            (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
                printf("pf_map_addr: selected address ");
                pf_print_host(naddr, 0, af);
+               if (nkif)
+                       printf("@%s", (*nkif)->pfik_name);
                printf("\n");
        }
 
@@ -711,7 +725,7 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int 
off,
                }
                break;
        case PF_RDR: {
-               if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
+               if (pf_map_addr(pd->af, r, saddr, naddr, NULL, NULL, sn))
                        goto notrans;
                if ((r->rpool.opts & PF_POOL_TYPEMASK) == PF_POOL_BITMASK)
                        PF_POOLMASK(naddr, naddr, &r->rpool.cur->addr.v.a.mask,

Reply via email to