On Tue, Jul 19, 2022 at 07:18:54PM +0200, Moritz Buhl wrote:
> A solution would be to move the allocation of the pf_anchor struct
> into a pool.  One final question would be regarding the size of the
> hiwat or hardlimit.  Any suggestions?

10 seems way to low.  We want to limit resource abuse.  But regular
users should never hit this.  Especially existing configurations
should still work after upgrade.

Perhaps 512 anchors.  Noone shoul ever need more than 512 anchors :-)

> Any other comments?

Please do not use PR_WAITOK in pool_init() unless you know what you
are doing.  I think it should work, but who knows.  The other pf
pools have 0 flags, just use that.

Comment says rs_malloc is needed to compile pfctl.  Have you tested
that?

Replacing M_WAITOK|M_CANFAIL|M_ZERO with PR_NOWAIT|PR_ZERO looks
wrong.  PR_WAITOK|PR_LIMITFAIL|PR_ZERO should do something equivalent.

I am not sure if pf_find_anchor() should fail if the limit is hit.
It uses only a temporary buffer.  All calls to pf_find_ruleset()
should be checked whether permanent failure, after the limit has
been reached, is what we want.  Or we keep the malloc there?

bluhm

> Index: sys/net/pf.c
> ===================================================================
> RCS file: /mount/openbsd/cvs/src/sys/net/pf.c,v
> retrieving revision 1.1135
> diff -u -p -r1.1135 pf.c
> --- sys/net/pf.c      28 Jun 2022 13:48:06 -0000      1.1135
> +++ sys/net/pf.c      19 Jul 2022 11:34:23 -0000
> @@ -269,6 +269,7 @@ void                       pf_log_matches(struct pf_pdesc 
> *
>  
>  extern struct pool pfr_ktable_pl;
>  extern struct pool pfr_kentry_pl;
> +extern struct pool pf_anchor_pl;
>  
>  struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
>       { &pf_state_pl, PFSTATE_HIWAT, PFSTATE_HIWAT },
> @@ -276,7 +277,8 @@ struct pf_pool_limit pf_pool_limits[PF_L
>       { &pf_frent_pl, PFFRAG_FRENT_HIWAT, PFFRAG_FRENT_HIWAT },
>       { &pfr_ktable_pl, PFR_KTABLE_HIWAT, PFR_KTABLE_HIWAT },
>       { &pfr_kentry_pl, PFR_KENTRY_HIWAT, PFR_KENTRY_HIWAT },
> -     { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS }
> +     { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS },
> +     { &pf_anchor_pl, PF_ANCHOR_HIWAT, PF_ANCHOR_HIWAT }
>  };
>  
>  #define BOUND_IFACE(r, k) \
> Index: sys/net/pf_ioctl.c
> ===================================================================
> RCS file: /mount/openbsd/cvs/src/sys/net/pf_ioctl.c,v
> retrieving revision 1.382
> diff -u -p -r1.382 pf_ioctl.c
> --- sys/net/pf_ioctl.c        26 Jun 2022 11:37:08 -0000      1.382
> +++ sys/net/pf_ioctl.c        19 Jul 2022 16:56:23 -0000
> @@ -191,6 +191,8 @@ pfattach(int num)
>           IPL_SOFTNET, 0, "pftag", NULL);
>       pool_init(&pf_pktdelay_pl, sizeof(struct pf_pktdelay), 0,
>           IPL_SOFTNET, 0, "pfpktdelay", NULL);
> +     pool_init(&pf_anchor_pl, sizeof(struct pf_anchor), 0,
> +         IPL_SOFTNET, PR_WAITOK, "pfanchor", NULL);
>  
>       hfsc_initialize();
>       pfr_initialize();
> @@ -200,6 +202,8 @@ pfattach(int num)
>  
>       pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
>           pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
> +     pool_sethardlimit(pf_pool_limits[PF_LIMIT_ANCHORS].pp,
> +         pf_pool_limits[PF_LIMIT_ANCHORS].limit, NULL, 0);
>  
>       if (physmem <= atop(100*1024*1024))
>               pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
> Index: sys/net/pf_ruleset.c
> ===================================================================
> RCS file: /mount/openbsd/cvs/src/sys/net/pf_ruleset.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 pf_ruleset.c
> --- sys/net/pf_ruleset.c      27 Dec 2018 16:54:01 -0000      1.18
> +++ sys/net/pf_ruleset.c      19 Jul 2022 12:56:35 -0000
> @@ -40,6 +40,7 @@
>  #ifdef _KERNEL
>  #include <sys/systm.h>
>  #include <sys/mbuf.h>
> +#include <sys/pool.h>
>  #endif /* _KERNEL */
>  #include <sys/syslog.h>
>  
> @@ -55,6 +56,7 @@
>  #endif /* INET6 */
>  
>  
> +struct pool  pf_anchor_pl;
>  #ifdef _KERNEL
>  #define rs_malloc(x)         malloc(x, M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO)
>  #define rs_free(x, siz)              free(x, M_TEMP, siz)
> @@ -107,12 +109,12 @@ pf_find_anchor(const char *path)
>  {
>       struct pf_anchor        *key, *found;
>  
> -     key = rs_malloc(sizeof(*key));
> +     key = pool_get(&pf_anchor_pl, PR_NOWAIT | PR_ZERO);
>       if (key == NULL)
>               return (NULL);
>       strlcpy(key->path, path, sizeof(key->path));
>       found = RB_FIND(pf_anchor_global, &pf_anchors, key);
> -     rs_free(key, sizeof(*key));
> +     pool_put(&pf_anchor_pl, key);
>       return (found);
>  }
>  
> @@ -184,7 +186,7 @@ pf_create_anchor(struct pf_anchor *paren
>           ((parent != NULL) && (strlen(parent->path) >= PF_ANCHOR_MAXPATH)))
>               return (NULL);
>  
> -     anchor = rs_malloc(sizeof(*anchor));
> +     anchor = pool_get(&pf_anchor_pl, PR_NOWAIT | PR_ZERO);
>       if (anchor == NULL)
>               return (NULL);
>  
> @@ -204,7 +206,7 @@ pf_create_anchor(struct pf_anchor *paren
>               DPFPRINTF(LOG_NOTICE,
>                   "%s: RB_INSERT to global '%s' '%s' collides with '%s' '%s'",
>                   __func__, anchor->path, anchor->name, dup->path, dup->name);
> -             rs_free(anchor, sizeof(*anchor));
> +             pool_put(&pf_anchor_pl, anchor);
>               return (NULL);
>       }
>  
> @@ -218,7 +220,7 @@ pf_create_anchor(struct pf_anchor *paren
>                           dup->path, dup->name);
>                       RB_REMOVE(pf_anchor_global, &pf_anchors,
>                           anchor);
> -                     rs_free(anchor, sizeof(*anchor));
> +                     pool_put(&pf_anchor_pl, anchor);
>                       return (NULL);
>               }
>       }
> @@ -300,7 +302,7 @@ pf_remove_if_empty_ruleset(struct pf_rul
>               if ((parent = ruleset->anchor->parent) != NULL)
>                       RB_REMOVE(pf_anchor_node, &parent->children,
>                           ruleset->anchor);
> -             rs_free(ruleset->anchor, sizeof(*(ruleset->anchor)));
> +             pool_put(&pf_anchor_pl, ruleset->anchor);
>               if (parent == NULL)
>                       return;
>               ruleset = &parent->ruleset;
> Index: sys/net/pfvar.h
> ===================================================================
> RCS file: /mount/openbsd/cvs/src/sys/net/pfvar.h,v
> retrieving revision 1.508
> diff -u -p -r1.508 pfvar.h
> --- sys/net/pfvar.h   26 Jun 2022 11:37:08 -0000      1.508
> +++ sys/net/pfvar.h   19 Jul 2022 16:34:54 -0000
> @@ -136,7 +136,7 @@ enum      { PFTM_TCP_FIRST_PACKET, PFTM_TCP_O
>  enum { PF_NOPFROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO };
>  enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS,
>         PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_PKTDELAY_PKTS,
> -       PF_LIMIT_MAX };
> +       PF_LIMIT_ANCHORS, PF_LIMIT_MAX };
>  #define PF_POOL_IDMASK               0x0f
>  enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM,
>         PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN, PF_POOL_LEASTSTATES };
> @@ -476,6 +476,7 @@ union pf_rule_ptr {
>  
>  #define      PF_ANCHOR_NAME_SIZE      64
>  #define      PF_ANCHOR_MAXPATH       (PATH_MAX - PF_ANCHOR_NAME_SIZE - 1)
> +#define      PF_ANCHOR_HIWAT         10
>  #define      PF_OPTIMIZER_TABLE_PFX  "__automatic_"
>  
>  struct pf_rule {
> @@ -1703,7 +1704,7 @@ extern u_int32_t                 ticket_pabuf;
>  extern struct pool            pf_src_tree_pl, pf_sn_item_pl, pf_rule_pl;
>  extern struct pool            pf_state_pl, pf_state_key_pl, pf_state_item_pl,
>                                   pf_rule_item_pl, pf_queue_pl,
> -                                 pf_pktdelay_pl;
> +                                 pf_pktdelay_pl, pf_anchor_pl;
>  extern struct pool            pf_state_scrub_pl;
>  extern struct ifnet          *sync_ifp;
>  extern struct pf_rule                 pf_default_rule;

Reply via email to