From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org, kuba@kernel.org,
pabeni@redhat.com, edumazet@google.com, fw@strlen.de
Subject: [PATCH net-next 05/19] netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests
Date: Wed, 25 Oct 2023 23:25:41 +0200 [thread overview]
Message-ID: <20231025212555.132775-6-pablo@netfilter.org> (raw)
In-Reply-To: <20231025212555.132775-1-pablo@netfilter.org>
From: Phil Sutter <phil@nwl.cc>
Rule reset is not concurrency-safe per-se, so multiple CPUs may reset
the same rule at the same time. At least counter and quota expressions
will suffer from value underruns in this case.
Prevent this by introducing dedicated locking callbacks for nfnetlink
and the asynchronous dump handling to serialize access.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_tables_api.c | 77 +++++++++++++++++++++++++++++------
1 file changed, 64 insertions(+), 13 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index d39990c3ae1d..03a306d15f43 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3551,6 +3551,23 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
return skb->len;
}
+static int nf_tables_dumpreset_rules(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
+ int ret;
+
+ /* Mutex is held is to prevent that two concurrent dump-and-reset calls
+ * do not underrun counters and quotas. The commit_mutex is used for
+ * the lack a better lock, this is not transaction path.
+ */
+ mutex_lock(&nft_net->commit_mutex);
+ ret = nf_tables_dump_rules(skb, cb);
+ mutex_unlock(&nft_net->commit_mutex);
+
+ return ret;
+}
+
static int nf_tables_dump_rules_start(struct netlink_callback *cb)
{
struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
@@ -3570,12 +3587,18 @@ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
return -ENOMEM;
}
}
- if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
- ctx->reset = true;
-
return 0;
}
+static int nf_tables_dumpreset_rules_start(struct netlink_callback *cb)
+{
+ struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
+
+ ctx->reset = true;
+
+ return nf_tables_dump_rules_start(cb);
+}
+
static int nf_tables_dump_rules_done(struct netlink_callback *cb)
{
struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
@@ -3636,12 +3659,9 @@ nf_tables_getrule_single(u32 portid, const struct nfnl_info *info,
static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
const struct nlattr * const nla[])
{
- struct nftables_pernet *nft_net = nft_pernet(info->net);
u32 portid = NETLINK_CB(skb).portid;
struct net *net = info->net;
struct sk_buff *skb2;
- bool reset = false;
- char *buf;
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = {
@@ -3655,15 +3675,46 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
}
- if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
- reset = true;
-
- skb2 = nf_tables_getrule_single(portid, info, nla, reset);
+ skb2 = nf_tables_getrule_single(portid, info, nla, false);
if (IS_ERR(skb2))
return PTR_ERR(skb2);
- if (!reset)
- return nfnetlink_unicast(skb2, net, portid);
+ return nfnetlink_unicast(skb2, net, portid);
+}
+
+static int nf_tables_getrule_reset(struct sk_buff *skb,
+ const struct nfnl_info *info,
+ const struct nlattr * const nla[])
+{
+ struct nftables_pernet *nft_net = nft_pernet(info->net);
+ u32 portid = NETLINK_CB(skb).portid;
+ struct net *net = info->net;
+ struct sk_buff *skb2;
+ char *buf;
+
+ if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
+ struct netlink_dump_control c = {
+ .start= nf_tables_dumpreset_rules_start,
+ .dump = nf_tables_dumpreset_rules,
+ .done = nf_tables_dump_rules_done,
+ .module = THIS_MODULE,
+ .data = (void *)nla,
+ };
+
+ return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
+ }
+
+ if (!try_module_get(THIS_MODULE))
+ return -EINVAL;
+ rcu_read_unlock();
+ mutex_lock(&nft_net->commit_mutex);
+ skb2 = nf_tables_getrule_single(portid, info, nla, true);
+ mutex_unlock(&nft_net->commit_mutex);
+ rcu_read_lock();
+ module_put(THIS_MODULE);
+
+ if (IS_ERR(skb2))
+ return PTR_ERR(skb2);
buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
nla_len(nla[NFTA_RULE_TABLE]),
@@ -8995,7 +9046,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
.policy = nft_rule_policy,
},
[NFT_MSG_GETRULE_RESET] = {
- .call = nf_tables_getrule,
+ .call = nf_tables_getrule_reset,
.type = NFNL_CB_RCU,
.attr_count = NFTA_RULE_MAX,
.policy = nft_rule_policy,
--
2.30.2
next prev parent reply other threads:[~2023-10-25 21:26 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-25 21:25 [PATCH net-next 00/19] Netfilter updates for net-next Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 01/19] netfilter: nft_set_rbtree: rename gc deactivate+erase function Pablo Neira Ayuso
2023-10-26 13:30 ` patchwork-bot+netdevbpf
2023-10-25 21:25 ` [PATCH net-next 02/19] netfilter: nft_set_rbtree: prefer sync gc to async worker Pablo Neira Ayuso
2023-11-03 17:34 ` Simon Horman
2023-11-03 17:55 ` Florian Westphal
2023-10-25 21:25 ` [PATCH net-next 03/19] netfilter: nf_tables: Open-code audit log call in nf_tables_getrule() Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 04/19] netfilter: nf_tables: Introduce nf_tables_getrule_single() Pablo Neira Ayuso
2023-10-25 21:25 ` Pablo Neira Ayuso [this message]
2023-10-25 21:25 ` [PATCH net-next 06/19] br_netfilter: use single forward hook for ip and arp Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 07/19] netfilter: conntrack: switch connlabels to atomic_t Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 08/19] netfilter: nf_tables: Drop pointless memset in nf_tables_dump_obj Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 09/19] netfilter: nf_tables: Unconditionally allocate nft_obj_filter Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 10/19] netfilter: nf_tables: A better name for nft_obj_filter Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 11/19] netfilter: nf_tables: Carry s_idx in nft_obj_dump_ctx Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 12/19] netfilter: nf_tables: nft_obj_filter fits into cb->ctx Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 13/19] netfilter: nf_tables: Carry reset boolean in nft_obj_dump_ctx Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 14/19] netfilter: nft_set_pipapo: no need to call pipapo_deactivate() from flush Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 15/19] netfilter: nf_tables: set backend .flush always succeeds Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 16/19] netfilter: nf_tables: expose opaque set element as struct nft_elem_priv Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 17/19] netfilter: nf_tables: shrink memory consumption of set elements Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 18/19] netfilter: nf_tables: set->ops->insert returns opaque set element in case of EEXIST Pablo Neira Ayuso
2023-10-25 21:25 ` [PATCH net-next 19/19] netfilter: nf_tables: Carry reset boolean in nft_set_dump_ctx Pablo Neira Ayuso
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=20231025212555.132775-6-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
/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).