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
This commit is contained in:
Kristof Provost 2018-02-25 08:56:44 +00:00
parent 22ae8ae1f4
commit bf56a3fe47
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329950
2 changed files with 33 additions and 7 deletions

View file

@ -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)

View file

@ -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);