mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 01:30:30 -04:00
pf: allocate pf_kanchor from a pool
Add a pool for the allocation of the pf_anchor struct. It was possible to exhaust kernel memory by repeatedly calling pfioctl DIOCXBEGIN with different anchor names. OK bluhm@ Reported-by: syzbot+9dd98cbce69e26f0fc11@syzkaller.appspotmail.com Obtained from: OpenBSD, mbuhl <mbuhl@openbsd.org>, fa90ac5c78 Obtained from: OpenBSD, mbuhl <mbuhl@openbsd.org>, c259202341 Sponsored by: Rubicon Communications, LLC ("Netgate")
This commit is contained in:
parent
17ac89e1df
commit
31131a9d6a
7 changed files with 19 additions and 5 deletions
|
|
@ -183,6 +183,7 @@ static const struct {
|
|||
{ "src-nodes", PF_LIMIT_SRC_NODES },
|
||||
{ "frags", PF_LIMIT_FRAGS },
|
||||
{ "table-entries", PF_LIMIT_TABLE_ENTRIES },
|
||||
{ "anchors", PF_LIMIT_ANCHORS },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2338,6 +2338,8 @@ VNET_DECLARE(uma_zone_t, pf_udp_mapping_z);
|
|||
#define V_pf_udp_mapping_z VNET(pf_udp_mapping_z)
|
||||
VNET_DECLARE(uma_zone_t, pf_state_scrub_z);
|
||||
#define V_pf_state_scrub_z VNET(pf_state_scrub_z)
|
||||
VNET_DECLARE(uma_zone_t, pf_anchor_z);
|
||||
#define V_pf_anchor_z VNET(pf_anchor_z)
|
||||
|
||||
extern void pf_purge_thread(void *);
|
||||
extern void pf_unload_vnet_purge(void);
|
||||
|
|
|
|||
|
|
@ -1254,6 +1254,14 @@ pf_initialize(void)
|
|||
MTX_DEF | MTX_DUPOK);
|
||||
}
|
||||
|
||||
/* Anchors */
|
||||
V_pf_anchor_z = uma_zcreate("pf anchors",
|
||||
sizeof(struct pf_kanchor), NULL, NULL, NULL, NULL,
|
||||
UMA_ALIGN_PTR, 0);
|
||||
V_pf_limits[PF_LIMIT_ANCHORS].zone = V_pf_anchor_z;
|
||||
uma_zone_set_max(V_pf_anchor_z, PF_ANCHOR_HIWAT);
|
||||
uma_zone_set_warning(V_pf_anchor_z, "PF anchor limit reached");
|
||||
|
||||
/* ALTQ */
|
||||
TAILQ_INIT(&V_pf_altqs[0]);
|
||||
TAILQ_INIT(&V_pf_altqs[1]);
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ enum {
|
|||
|
||||
enum { PF_NOPFROUTE, PF_FASTROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO };
|
||||
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS,
|
||||
PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX };
|
||||
PF_LIMIT_TABLE_ENTRIES, 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 };
|
||||
|
|
@ -490,6 +490,7 @@ struct pf_osfp_ioctl {
|
|||
|
||||
#define PF_ANCHOR_NAME_SIZE 64
|
||||
#define PF_ANCHOR_MAXPATH (MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)
|
||||
#define PF_ANCHOR_HIWAT 512
|
||||
#define PF_OPTIMIZER_TABLE_PFX "__automatic_"
|
||||
|
||||
struct pf_rule {
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ pfattach_vnet(void)
|
|||
|
||||
V_pf_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
|
||||
V_pf_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
|
||||
V_pf_limits[PF_LIMIT_ANCHORS].limit = PF_ANCHOR_HIWAT;
|
||||
|
||||
RB_INIT(&V_pf_anchors);
|
||||
pf_init_kruleset(&pf_main_ruleset);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ VNET_DEFINE_STATIC(uma_zone_t, pf_frnode_z);
|
|||
#define V_pf_frnode_z VNET(pf_frnode_z)
|
||||
VNET_DEFINE_STATIC(uma_zone_t, pf_frag_z);
|
||||
#define V_pf_frag_z VNET(pf_frag_z)
|
||||
VNET_DEFINE(uma_zone_t, pf_anchor_z);
|
||||
|
||||
TAILQ_HEAD(pf_fragqueue, pf_fragment);
|
||||
TAILQ_HEAD(pf_cachequeue, pf_fragment);
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ pf_create_kanchor(struct pf_kanchor *parent, const char *aname)
|
|||
((parent != NULL) && (strlen(parent->path) >= PF_ANCHOR_MAXPATH)))
|
||||
return (NULL);
|
||||
|
||||
anchor = rs_malloc(sizeof(*anchor));
|
||||
anchor = uma_zalloc(V_pf_anchor_z, M_NOWAIT | M_ZERO);
|
||||
if (anchor == NULL)
|
||||
return (NULL);
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ pf_create_kanchor(struct pf_kanchor *parent, const char *aname)
|
|||
printf("%s: RB_INSERT1 "
|
||||
"'%s' '%s' collides with '%s' '%s'\n", __func__,
|
||||
anchor->path, anchor->name, dup->path, dup->name);
|
||||
rs_free(anchor);
|
||||
uma_zfree(V_pf_anchor_z, anchor);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
|
@ -273,7 +273,7 @@ pf_create_kanchor(struct pf_kanchor *parent, const char *aname)
|
|||
anchor->name, dup->path, dup->name);
|
||||
RB_REMOVE(pf_kanchor_global, &V_pf_anchors,
|
||||
anchor);
|
||||
rs_free(anchor);
|
||||
uma_zfree(V_pf_anchor_z, anchor);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -350,7 +350,7 @@ pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset)
|
|||
if ((parent = ruleset->anchor->parent) != NULL)
|
||||
RB_REMOVE(pf_kanchor_node, &parent->children,
|
||||
ruleset->anchor);
|
||||
rs_free(ruleset->anchor);
|
||||
uma_zfree(V_pf_anchor_z, ruleset->anchor);
|
||||
if (parent == NULL)
|
||||
return;
|
||||
ruleset = &parent->ruleset;
|
||||
|
|
|
|||
Loading…
Reference in a new issue