diff options
author | mm <mm@FreeBSD.org> | 2014-04-27 09:05:34 +0000 |
---|---|---|
committer | mm <mm@FreeBSD.org> | 2014-04-27 09:05:34 +0000 |
commit | 5b89692b00a51ee27c4f004b3c954b0b123bf551 (patch) | |
tree | 4057c670b23905e051d5000aca915b4be3d33852 | |
parent | 1e4589b921fdaa1b1d2fc6b6ed016f1e0a01cb8f (diff) | |
download | FreeBSD-src-5b89692b00a51ee27c4f004b3c954b0b123bf551.zip FreeBSD-src-5b89692b00a51ee27c4f004b3c954b0b123bf551.tar.gz |
MFC r264689:
De-virtualize UMA zone pf_mtag_z and move to global initialization part.
The m_tag struct does not know about vnet context and the pf_mtag_free()
callback is called unaware of current vnet. This causes a panic.
PR: kern/182964
-rw-r--r-- | sys/net/pfvar.h | 2 | ||||
-rw-r--r-- | sys/netpfil/pf/pf.c | 34 | ||||
-rw-r--r-- | sys/netpfil/pf/pf_ioctl.c | 4 |
3 files changed, 28 insertions, 12 deletions
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index b7fbf5f..0dc362a 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1531,6 +1531,8 @@ VNET_DECLARE(struct pf_rulequeue, pf_unlinked_rules); #define V_pf_unlinked_rules VNET(pf_unlinked_rules) void pf_initialize(void); +void pf_mtag_initialize(void); +void pf_mtag_cleanup(void); void pf_cleanup(void); struct pf_mtag *pf_get_mtag(struct mbuf *); diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index c6840fd..980db13 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -186,8 +186,7 @@ struct mtx pf_unlnkdrules_mtx; static VNET_DEFINE(uma_zone_t, pf_sources_z); #define V_pf_sources_z VNET(pf_sources_z) -static VNET_DEFINE(uma_zone_t, pf_mtag_z); -#define V_pf_mtag_z VNET(pf_mtag_z) +uma_zone_t pf_mtag_z; VNET_DEFINE(uma_zone_t, pf_state_z); VNET_DEFINE(uma_zone_t, pf_state_key_z); @@ -282,7 +281,7 @@ static int pf_insert_src_node(struct pf_src_node **, struct pf_rule *, struct pf_addr *, sa_family_t); static u_int pf_purge_expired_states(u_int, int); static void pf_purge_unlinked_rules(void); -static int pf_mtag_init(void *, int, int); +static int pf_mtag_uminit(void *, int, int); static void pf_mtag_free(struct m_tag *); #ifdef INET static void pf_route(struct mbuf **, struct pf_rule *, int, @@ -727,7 +726,16 @@ pf_free_src_nodes(struct pf_src_node_list *head) return (count); } -/* Data storage structures initialization. */ +void +pf_mtag_initialize() +{ + + pf_mtag_z = uma_zcreate("pf mtags", sizeof(struct m_tag) + + sizeof(struct pf_mtag), NULL, NULL, pf_mtag_uminit, NULL, + UMA_ALIGN_PTR, 0); +} + +/* Per-vnet data storage structures initialization. */ void pf_initialize() { @@ -786,10 +794,6 @@ pf_initialize() V_pf_altqs_active = &V_pf_altqs[0]; V_pf_altqs_inactive = &V_pf_altqs[1]; - /* Mbuf tags */ - V_pf_mtag_z = uma_zcreate("pf mtags", sizeof(struct m_tag) + - sizeof(struct pf_mtag), NULL, NULL, pf_mtag_init, NULL, - UMA_ALIGN_PTR, 0); /* Send & overload+flush queues. */ STAILQ_INIT(&V_pf_sendqueue); @@ -805,6 +809,13 @@ pf_initialize() } void +pf_mtag_cleanup() +{ + + uma_zdestroy(pf_mtag_z); +} + +void pf_cleanup() { struct pf_keyhash *kh; @@ -841,14 +852,13 @@ pf_cleanup() mtx_destroy(&pf_overloadqueue_mtx); mtx_destroy(&pf_unlnkdrules_mtx); - uma_zdestroy(V_pf_mtag_z); uma_zdestroy(V_pf_sources_z); uma_zdestroy(V_pf_state_z); uma_zdestroy(V_pf_state_key_z); } static int -pf_mtag_init(void *mem, int size, int how) +pf_mtag_uminit(void *mem, int size, int how) { struct m_tag *t; @@ -865,7 +875,7 @@ static void pf_mtag_free(struct m_tag *t) { - uma_zfree(V_pf_mtag_z, t); + uma_zfree(pf_mtag_z, t); } struct pf_mtag * @@ -876,7 +886,7 @@ pf_get_mtag(struct mbuf *m) if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) != NULL) return ((struct pf_mtag *)(mtag + 1)); - mtag = uma_zalloc(V_pf_mtag_z, M_NOWAIT); + mtag = uma_zalloc(pf_mtag_z, M_NOWAIT); if (mtag == NULL) return (NULL); bzero(mtag + 1, sizeof(struct pf_mtag)); diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index aa42040..ef44806 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -204,6 +204,8 @@ pfattach(void) u_int32_t *my_timeout = V_pf_default_rule.timeout; int error; + if (IS_DEFAULT_VNET(curvnet)) + pf_mtag_initialize(); pf_initialize(); pfr_initialize(); pfi_initialize(); @@ -3721,6 +3723,8 @@ pf_unload(void) pfr_cleanup(); pf_osfp_flush(); pf_cleanup(); + if (IS_DEFAULT_VNET(curvnet)) + pf_mtag_cleanup(); PF_RULES_WUNLOCK(); destroy_dev(pf_dev); rw_destroy(&pf_rules_lock); |