git: d10de21f2f7d - main - pf: Access r->rpool.cur->kif under mutex protection
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 24 Aug 2023 13:08:22 UTC
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=d10de21f2f7df59344f8611546989b36e4fd867c commit d10de21f2f7df59344f8611546989b36e4fd867c Author: Kajetan Staszkiewicz <vegeta@tuxpowered.net> AuthorDate: 2023-08-24 11:05:33 +0000 Commit: Kristof Provost <kp@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,