netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org
Subject: [PATCH 28/38] netfilter: nf_tables: add and use helper for module autoload
Date: Fri, 20 Jul 2018 15:08:56 +0200	[thread overview]
Message-ID: <20180720130906.27687-29-pablo@netfilter.org> (raw)
In-Reply-To: <20180720130906.27687-1-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

module autoload is problematic, it requires dropping the mutex that
protects the transaction.  Once the mutex has been dropped, another
client can start a new transaction before we had a chance to abort
current transaction log.

This helper makes sure we first zap the transaction log, then
drop mutex for module autoload.

In case autload is successful, the caller has to reply entire
message anyway.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_tables_api.c | 81 +++++++++++++++++++++++++++----------------
 1 file changed, 52 insertions(+), 29 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 3f211e1025c1..5e95e92e547b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -455,8 +455,40 @@ __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)
 	return NULL;
 }
 
+/*
+ * Loading a module requires dropping mutex that guards the
+ * transaction.
+ * We first need to abort any pending transactions as once
+ * mutex is unlocked a different client could start a new
+ * transaction.  It must not see any 'future generation'
+ * changes * as these changes will never happen.
+ */
+#ifdef CONFIG_MODULES
+static int __nf_tables_abort(struct net *net);
+
+static void nft_request_module(struct net *net, const char *fmt, ...)
+{
+	char module_name[MODULE_NAME_LEN];
+	va_list args;
+	int ret;
+
+	__nf_tables_abort(net);
+
+	va_start(args, fmt);
+	ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
+	va_end(args);
+	if (WARN(ret >= MODULE_NAME_LEN, "truncated: '%s' (len %d)", module_name, ret))
+		return;
+
+	nfnl_unlock(NFNL_SUBSYS_NFTABLES);
+	request_module("%s", module_name);
+	nfnl_lock(NFNL_SUBSYS_NFTABLES);
+}
+#endif
+
 static const struct nft_chain_type *
-nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)
+nf_tables_chain_type_lookup(struct net *net, const struct nlattr *nla,
+			    u8 family, bool autoload)
 {
 	const struct nft_chain_type *type;
 
@@ -465,10 +497,8 @@ nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family, bool autoload)
 		return type;
 #ifdef CONFIG_MODULES
 	if (autoload) {
-		nfnl_unlock(NFNL_SUBSYS_NFTABLES);
-		request_module("nft-chain-%u-%.*s", family,
-			       nla_len(nla), (const char *)nla_data(nla));
-		nfnl_lock(NFNL_SUBSYS_NFTABLES);
+		nft_request_module(net, "nft-chain-%u-%.*s", family,
+				   nla_len(nla), (const char *)nla_data(nla));
 		type = __nf_tables_chain_type_lookup(nla, family);
 		if (type != NULL)
 			return ERR_PTR(-EAGAIN);
@@ -1412,7 +1442,7 @@ static int nft_chain_parse_hook(struct net *net,
 
 	type = chain_type[family][NFT_CHAIN_T_DEFAULT];
 	if (nla[NFTA_CHAIN_TYPE]) {
-		type = nf_tables_chain_type_lookup(nla[NFTA_CHAIN_TYPE],
+		type = nf_tables_chain_type_lookup(net, nla[NFTA_CHAIN_TYPE],
 						   family, create);
 		if (IS_ERR(type))
 			return PTR_ERR(type);
@@ -1875,7 +1905,8 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family,
 	return NULL;
 }
 
-static const struct nft_expr_type *nft_expr_type_get(u8 family,
+static const struct nft_expr_type *nft_expr_type_get(struct net *net,
+						     u8 family,
 						     struct nlattr *nla)
 {
 	const struct nft_expr_type *type;
@@ -1889,17 +1920,13 @@ static const struct nft_expr_type *nft_expr_type_get(u8 family,
 
 #ifdef CONFIG_MODULES
 	if (type == NULL) {
-		nfnl_unlock(NFNL_SUBSYS_NFTABLES);
-		request_module("nft-expr-%u-%.*s", family,
-			       nla_len(nla), (char *)nla_data(nla));
-		nfnl_lock(NFNL_SUBSYS_NFTABLES);
+		nft_request_module(net, "nft-expr-%u-%.*s", family,
+				   nla_len(nla), (char *)nla_data(nla));
 		if (__nft_expr_type_get(family, nla))
 			return ERR_PTR(-EAGAIN);
 
-		nfnl_unlock(NFNL_SUBSYS_NFTABLES);
-		request_module("nft-expr-%.*s",
-			       nla_len(nla), (char *)nla_data(nla));
-		nfnl_lock(NFNL_SUBSYS_NFTABLES);
+		nft_request_module(net, "nft-expr-%.*s",
+				   nla_len(nla), (char *)nla_data(nla));
 		if (__nft_expr_type_get(family, nla))
 			return ERR_PTR(-EAGAIN);
 	}
@@ -1968,7 +1995,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
 	if (err < 0)
 		return err;
 
-	type = nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]);
+	type = nft_expr_type_get(ctx->net, ctx->family, tb[NFTA_EXPR_NAME]);
 	if (IS_ERR(type))
 		return PTR_ERR(type);
 
@@ -2744,9 +2771,7 @@ nft_select_set_ops(const struct nft_ctx *ctx,
 
 #ifdef CONFIG_MODULES
 	if (list_empty(&nf_tables_set_types)) {
-		nfnl_unlock(NFNL_SUBSYS_NFTABLES);
-		request_module("nft-set");
-		nfnl_lock(NFNL_SUBSYS_NFTABLES);
+		nft_request_module(ctx->net, "nft-set");
 		if (!list_empty(&nf_tables_set_types))
 			return ERR_PTR(-EAGAIN);
 	}
@@ -4779,7 +4804,8 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
 	return NULL;
 }
 
-static const struct nft_object_type *nft_obj_type_get(u32 objtype)
+static const struct nft_object_type *
+nft_obj_type_get(struct net *net, u32 objtype)
 {
 	const struct nft_object_type *type;
 
@@ -4789,9 +4815,7 @@ static const struct nft_object_type *nft_obj_type_get(u32 objtype)
 
 #ifdef CONFIG_MODULES
 	if (type == NULL) {
-		nfnl_unlock(NFNL_SUBSYS_NFTABLES);
-		request_module("nft-obj-%u", objtype);
-		nfnl_lock(NFNL_SUBSYS_NFTABLES);
+		nft_request_module(net, "nft-obj-%u", objtype);
 		if (__nft_obj_type_get(objtype))
 			return ERR_PTR(-EAGAIN);
 	}
@@ -4843,7 +4867,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
 
 	nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
 
-	type = nft_obj_type_get(objtype);
+	type = nft_obj_type_get(net, objtype);
 	if (IS_ERR(type))
 		return PTR_ERR(type);
 
@@ -5339,7 +5363,8 @@ static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)
 	return NULL;
 }
 
-static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)
+static const struct nf_flowtable_type *
+nft_flowtable_type_get(struct net *net, u8 family)
 {
 	const struct nf_flowtable_type *type;
 
@@ -5349,9 +5374,7 @@ static const struct nf_flowtable_type *nft_flowtable_type_get(u8 family)
 
 #ifdef CONFIG_MODULES
 	if (type == NULL) {
-		nfnl_unlock(NFNL_SUBSYS_NFTABLES);
-		request_module("nf-flowtable-%u", family);
-		nfnl_lock(NFNL_SUBSYS_NFTABLES);
+		nft_request_module(net, "nf-flowtable-%u", family);
 		if (__nft_flowtable_type_get(family))
 			return ERR_PTR(-EAGAIN);
 	}
@@ -5431,7 +5454,7 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
 		goto err1;
 	}
 
-	type = nft_flowtable_type_get(family);
+	type = nft_flowtable_type_get(net, family);
 	if (IS_ERR(type)) {
 		err = PTR_ERR(type);
 		goto err2;
-- 
2.11.0

  parent reply	other threads:[~2018-07-20 13:08 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-20 13:08 [PATCH 00/38] Netfilter/IPVS updates for net-next Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 01/38] netfilter: nft_reject_bridge: remove unnecessary ttl set Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 02/38] netfilter: flowtables: use fixed renew timeout on teardown Pablo Neira Ayuso
2018-07-20 13:20   ` Felix Fietkau
2018-07-20 13:32     ` Florian Westphal
2018-07-20 13:08 ` [PATCH 03/38] netfilter: nft_tproxy: Move nf_tproxy_assign_sock() to nf_tproxy.h Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 04/38] netfilter: utils: move nf_ip_checksum* from ipv4 to utils Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 05/38] netfilter: utils: move nf_ip6_checksum* from ipv6 " Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 06/38] openvswitch: use nf_ct_get_tuplepr, invert_tuplepr Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 07/38] netfilter: Kconfig: Make NETFILTER_XT_MATCH_SOCKET select NF_SOCKET_IPV4/6 Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 08/38] netfilter: conntrack: remove ctnetlink callbacks from l3 protocol trackers Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 09/38] netfilter: conntrack: remove pkt_to_tuple indirection " Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 10/38] netfilter: conntrack: remove invert_tuple " Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 11/38] netfilter: conntrack: remove get_l4proto " Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 12/38] netfilter: conntrack: avoid calls to l4proto invert_tuple Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 13/38] netfilter: conntrack: avoid l4proto pkt_to_tuple calls Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 14/38] netfilter: conntrack: remove get_timeout() indirection Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 15/38] netfilter: conntrack: remove l3proto abstraction Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 16/38] netfilter: Kconfig: Change select IPv6 dependencies Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 17/38] netfilter: nf_conncount: Early exit for garbage collection Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 18/38] netfilter: nf_conncount: Switch to plain list Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 19/38] netfilter: nf_conncount: Early exit in nf_conncount_lookup() and cleanup Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 20/38] netfilter: nf_conncount: Move locking into count_tree() Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 21/38] netfilter: nf_conncount: Split insert and traversal Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 22/38] netfilter: nf_conncount: Add list lock and gc worker, and RCU for init tree search Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 23/38] netfilter: nf_conntrack: resolve clash for matching conntracks Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 24/38] ipvs: provide just conn to ip_vs_state_name Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 25/38] ipvs: add assured state for conn templates Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 26/38] ipvs: drop conn templates under attack Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 27/38] netfilter: Remove useless param helper of nf_ct_helper_ext_add Pablo Neira Ayuso
2018-07-20 13:08 ` Pablo Neira Ayuso [this message]
2018-07-20 13:08 ` [PATCH 29/38] netfilter: nf_tables: make valid_genid callback mandatory Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 30/38] netfilter: nf_tables: take module reference when starting a batch Pablo Neira Ayuso
2018-07-20 13:08 ` [PATCH 31/38] netfilter: nf_tables: avoid global info storage Pablo Neira Ayuso
2018-07-20 13:09 ` [PATCH 32/38] netfilter: nf_tables: use dedicated mutex to guard transactions Pablo Neira Ayuso
2018-07-20 13:09 ` [PATCH 33/38] netfilter: nf_osf: add nf_osf_match_one() Pablo Neira Ayuso
2018-07-20 13:09 ` [PATCH 34/38] netfilter: nf_osf: add struct nf_osf_hdr_ctx Pablo Neira Ayuso
2018-07-20 13:09 ` [PATCH 35/38] netfilter: nft_socket: Break evaluation if no socket found Pablo Neira Ayuso
2018-07-20 13:09 ` [PATCH 36/38] netfilter: nft_socket: Expose socket mark Pablo Neira Ayuso
2018-07-20 13:09 ` [PATCH 37/38] ipv6: remove dependency of nf_defrag_ipv6 on ipv6 module Pablo Neira Ayuso
2018-07-20 13:09 ` [PATCH 38/38] netfilter: nf_osf: add missing definitions to header file Pablo Neira Ayuso
2018-07-21  6:33 ` [PATCH 00/38] Netfilter/IPVS updates for net-next David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180720130906.27687-29-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).