Author: kp
Date: Sun Feb 25 08:56:44 2018
New Revision: 329950
URL: https://svnweb.freebsd.org/changeset/base/329950

Log:
  pf: Cope with overly large net.pf.states_hashsize
  
  If the user configures a states_hashsize or source_nodes_hashsize value we may
  not have enough memory to allocate this. This used to lock up pf, because 
these
  allocations used M_WAITOK.
  
  Cope with this by attempting the allocation with M_NOWAIT and falling back to
  the default sizes (with M_WAITOK) if these fail.
  
  PR:           209475
  Submitted by: Fehmi Noyan Isi <fnoyanisi AT yahoo.com>
  MFC after:    3 weeks
  Differential Revision:        https://reviews.freebsd.org/D14367

Modified:
  head/sys/net/pfvar.h
  head/sys/netpfil/pf/pf.c

Modified: head/sys/net/pfvar.h
==============================================================================
--- head/sys/net/pfvar.h        Sun Feb 25 05:14:06 2018        (r329949)
+++ head/sys/net/pfvar.h        Sun Feb 25 08:56:44 2018        (r329950)
@@ -1467,6 +1467,7 @@ struct pf_idhash {
 extern u_long          pf_hashmask;
 extern u_long          pf_srchashmask;
 #define        PF_HASHSIZ      (32768)
+#define        PF_SRCHASHSIZ   (PF_HASHSIZ/4)
 VNET_DECLARE(struct pf_keyhash *, pf_keyhash);
 VNET_DECLARE(struct pf_idhash *, pf_idhash);
 #define V_pf_keyhash   VNET(pf_keyhash)

Modified: head/sys/netpfil/pf/pf.c
==============================================================================
--- head/sys/netpfil/pf/pf.c    Sun Feb 25 05:14:06 2018        (r329949)
+++ head/sys/netpfil/pf/pf.c    Sun Feb 25 08:56:44 2018        (r329950)
@@ -790,7 +790,7 @@ pf_initialize()
        if (pf_hashsize == 0 || !powerof2(pf_hashsize))
                pf_hashsize = PF_HASHSIZ;
        if (pf_srchashsize == 0 || !powerof2(pf_srchashsize))
-               pf_srchashsize = PF_HASHSIZ / 4;
+               pf_srchashsize = PF_SRCHASHSIZ;
 
        V_pf_hashseed = arc4random();
 
@@ -804,10 +804,25 @@ pf_initialize()
        V_pf_state_key_z = uma_zcreate("pf state keys",
            sizeof(struct pf_state_key), pf_state_key_ctor, NULL, NULL, NULL,
            UMA_ALIGN_PTR, 0);
-       V_pf_keyhash = malloc(pf_hashsize * sizeof(struct pf_keyhash),
-           M_PFHASH, M_WAITOK | M_ZERO);
-       V_pf_idhash = malloc(pf_hashsize * sizeof(struct pf_idhash),
-           M_PFHASH, M_WAITOK | M_ZERO);
+
+       V_pf_keyhash = mallocarray(pf_hashsize, sizeof(struct pf_keyhash),
+           M_PFHASH, M_NOWAIT | M_ZERO);
+       V_pf_idhash = mallocarray(pf_hashsize, sizeof(struct pf_idhash),
+           M_PFHASH, M_NOWAIT | M_ZERO);
+       if (V_pf_keyhash == NULL || V_pf_idhash == NULL) {
+               printf("pf: Unable to allocate memory for "
+                   "state_hashsize %lu.\n", pf_hashsize);
+
+               free(V_pf_keyhash, M_PFHASH);
+               free(V_pf_idhash, M_PFHASH);
+
+               pf_hashsize = PF_HASHSIZ;
+               V_pf_keyhash = mallocarray(pf_hashsize,
+                   sizeof(struct pf_keyhash), M_PFHASH, M_WAITOK | M_ZERO);
+               V_pf_idhash = mallocarray(pf_hashsize,
+                   sizeof(struct pf_idhash), M_PFHASH, M_WAITOK | M_ZERO);
+       }
+
        pf_hashmask = pf_hashsize - 1;
        for (i = 0, kh = V_pf_keyhash, ih = V_pf_idhash; i <= pf_hashmask;
            i++, kh++, ih++) {
@@ -822,8 +837,18 @@ pf_initialize()
        V_pf_limits[PF_LIMIT_SRC_NODES].zone = V_pf_sources_z;
        uma_zone_set_max(V_pf_sources_z, PFSNODE_HIWAT);
        uma_zone_set_warning(V_pf_sources_z, "PF source nodes limit reached");
-       V_pf_srchash = malloc(pf_srchashsize * sizeof(struct pf_srchash),
-         M_PFHASH, M_WAITOK|M_ZERO);
+
+       V_pf_srchash = mallocarray(pf_srchashsize,
+           sizeof(struct pf_srchash), M_PFHASH, M_NOWAIT | M_ZERO);
+       if (V_pf_srchash == NULL) {
+               printf("pf: Unable to allocate memory for "
+                   "source_hashsize %lu.\n", pf_srchashsize);
+
+               pf_srchashsize = PF_SRCHASHSIZ;
+               V_pf_srchash = mallocarray(pf_srchashsize,
+                   sizeof(struct pf_srchash), M_PFHASH, M_WAITOK | M_ZERO);
+       }
+
        pf_srchashmask = pf_srchashsize - 1;
        for (i = 0, sh = V_pf_srchash; i <= pf_srchashmask; i++, sh++)
                mtx_init(&sh->lock, "pf_srchash", NULL, MTX_DEF);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to