netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback
@ 2023-09-29 19:19 Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 1/5] netfilter: nf_tables: Always allocate nft_rule_dump_ctx Phil Sutter
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Phil Sutter @ 2023-09-29 19:19 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

Struct netlink_callback has a 48byte scratch area for use by dump
callbacks to keep personal stuff.

In rule dumps set up by nf_tables_getrule(), this is used only to store
a cursor into the list of rules being dumped. Other data is allocated
and the pointer value assigned to struct netlink_callback::data.

Since the allocated data structure is small and fits into the scratch
area even after adding some more fields, move it there.

Patch 1 "simplifies" nf_tables_dump_rules_start() a bit, but actually
exists only to reduce patch 5's size.

Patch 2 is more or less fallout: The memset would mess things up after
this series, but it was pointless in the first place.

Patches 3 and 4 extend struct nft_rule_dump_ctx and make
struct netlink_callback's scratch area unused.

Patch 5 then finally eliminates the allocation.

All this is early preparation for reset command locking but unrelated
enough to go alone.

Phil Sutter (5):
  netfilter: nf_tables: Always allocate nft_rule_dump_ctx
  netfilter: nf_tables: Drop pointless memset when dumping rules
  netfilter: nf_tables: Carry reset flag in nft_rule_dump_ctx
  netfilter: nf_tables: Carry s_idx in nft_rule_dump_ctx
  netfilter: nf_tables: Don't allocate nft_rule_dump_ctx

 net/netfilter/nf_tables_api.c | 80 ++++++++++++++---------------------
 1 file changed, 31 insertions(+), 49 deletions(-)

-- 
2.41.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [nf-next PATCH 1/5] netfilter: nf_tables: Always allocate nft_rule_dump_ctx
  2023-09-29 19:19 [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Phil Sutter
@ 2023-09-29 19:19 ` Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 2/5] netfilter: nf_tables: Drop pointless memset when dumping rules Phil Sutter
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Phil Sutter @ 2023-09-29 19:19 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

It will move into struct netlink_callback's scratch area later, just put
nf_tables_dump_rules_start in shape to reduce churn later.

Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 net/netfilter/nf_tables_api.c | 48 +++++++++++++++--------------------
 1 file changed, 21 insertions(+), 27 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 4356189360fb8..c033671baa7e7 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3521,10 +3521,10 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 		if (family != NFPROTO_UNSPEC && family != table->family)
 			continue;
 
-		if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
+		if (ctx->table && strcmp(ctx->table, table->name) != 0)
 			continue;
 
-		if (ctx && ctx->table && ctx->chain) {
+		if (ctx->table && ctx->chain) {
 			struct rhlist_head *list, *tmp;
 
 			list = rhltable_lookup(&table->chains_ht, ctx->chain,
@@ -3548,7 +3548,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 				goto done;
 		}
 
-		if (ctx && ctx->table)
+		if (ctx->table)
 			break;
 	}
 done:
@@ -3563,27 +3563,23 @@ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
 	const struct nlattr * const *nla = cb->data;
 	struct nft_rule_dump_ctx *ctx = NULL;
 
-	if (nla[NFTA_RULE_TABLE] || nla[NFTA_RULE_CHAIN]) {
-		ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
-		if (!ctx)
-			return -ENOMEM;
+	ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
+	if (!ctx)
+		return -ENOMEM;
 
-		if (nla[NFTA_RULE_TABLE]) {
-			ctx->table = nla_strdup(nla[NFTA_RULE_TABLE],
-							GFP_ATOMIC);
-			if (!ctx->table) {
-				kfree(ctx);
-				return -ENOMEM;
-			}
+	if (nla[NFTA_RULE_TABLE]) {
+		ctx->table = nla_strdup(nla[NFTA_RULE_TABLE], GFP_ATOMIC);
+		if (!ctx->table) {
+			kfree(ctx);
+			return -ENOMEM;
 		}
-		if (nla[NFTA_RULE_CHAIN]) {
-			ctx->chain = nla_strdup(nla[NFTA_RULE_CHAIN],
-						GFP_ATOMIC);
-			if (!ctx->chain) {
-				kfree(ctx->table);
-				kfree(ctx);
-				return -ENOMEM;
-			}
+	}
+	if (nla[NFTA_RULE_CHAIN]) {
+		ctx->chain = nla_strdup(nla[NFTA_RULE_CHAIN], GFP_ATOMIC);
+		if (!ctx->chain) {
+			kfree(ctx->table);
+			kfree(ctx);
+			return -ENOMEM;
 		}
 	}
 
@@ -3595,11 +3591,9 @@ static int nf_tables_dump_rules_done(struct netlink_callback *cb)
 {
 	struct nft_rule_dump_ctx *ctx = cb->data;
 
-	if (ctx) {
-		kfree(ctx->table);
-		kfree(ctx->chain);
-		kfree(ctx);
-	}
+	kfree(ctx->table);
+	kfree(ctx->chain);
+	kfree(ctx);
 	return 0;
 }
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [nf-next PATCH 2/5] netfilter: nf_tables: Drop pointless memset when dumping rules
  2023-09-29 19:19 [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 1/5] netfilter: nf_tables: Always allocate nft_rule_dump_ctx Phil Sutter
@ 2023-09-29 19:19 ` Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 3/5] netfilter: nf_tables: Carry reset flag in nft_rule_dump_ctx Phil Sutter
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Phil Sutter @ 2023-09-29 19:19 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

None of the dump callbacks uses netlink_callback::args beyond the first
element, no need to zero the data.

Fixes: 96518518cc417 ("netfilter: add nftables")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 net/netfilter/nf_tables_api.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index c033671baa7e7..8ae87a32753b2 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3465,10 +3465,6 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
 			goto cont_skip;
 		if (*idx < s_idx)
 			goto cont;
-		if (*idx > s_idx) {
-			memset(&cb->args[1], 0,
-					sizeof(cb->args) - sizeof(cb->args[0]));
-		}
 		if (prule)
 			handle = prule->handle;
 		else
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [nf-next PATCH 3/5] netfilter: nf_tables: Carry reset flag in nft_rule_dump_ctx
  2023-09-29 19:19 [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 1/5] netfilter: nf_tables: Always allocate nft_rule_dump_ctx Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 2/5] netfilter: nf_tables: Drop pointless memset when dumping rules Phil Sutter
@ 2023-09-29 19:19 ` Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 4/5] netfilter: nf_tables: Carry s_idx " Phil Sutter
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Phil Sutter @ 2023-09-29 19:19 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

This relieves the dump callback from having to check nlmsg_type upon
each call and instead performs the check once in .start callback.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 net/netfilter/nf_tables_api.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 8ae87a32753b2..21dd6a27ca598 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3443,15 +3443,16 @@ static void audit_log_rule_reset(const struct nft_table *table,
 struct nft_rule_dump_ctx {
 	char *table;
 	char *chain;
+	bool reset;
 };
 
 static int __nf_tables_dump_rules(struct sk_buff *skb,
 				  unsigned int *idx,
 				  struct netlink_callback *cb,
 				  const struct nft_table *table,
-				  const struct nft_chain *chain,
-				  bool reset)
+				  const struct nft_chain *chain)
 {
+	struct nft_rule_dump_ctx *ctx = cb->data;
 	struct net *net = sock_net(skb->sk);
 	const struct nft_rule *rule, *prule;
 	unsigned int s_idx = cb->args[0];
@@ -3475,7 +3476,7 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
 					NFT_MSG_NEWRULE,
 					NLM_F_MULTI | NLM_F_APPEND,
 					table->family,
-					table, chain, rule, handle, reset) < 0) {
+					table, chain, rule, handle, ctx->reset) < 0) {
 			ret = 1;
 			break;
 		}
@@ -3487,7 +3488,7 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
 		(*idx)++;
 	}
 
-	if (reset && entries)
+	if (ctx->reset && entries)
 		audit_log_rule_reset(table, cb->seq, entries);
 
 	return ret;
@@ -3504,10 +3505,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 	struct net *net = sock_net(skb->sk);
 	int family = nfmsg->nfgen_family;
 	struct nftables_pernet *nft_net;
-	bool reset = false;
-
-	if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
-		reset = true;
 
 	rcu_read_lock();
 	nft_net = nft_pernet(net);
@@ -3532,7 +3529,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 				if (!nft_is_active(net, chain))
 					continue;
 				__nf_tables_dump_rules(skb, &idx,
-						       cb, table, chain, reset);
+						       cb, table, chain);
 				break;
 			}
 			goto done;
@@ -3540,7 +3537,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 
 		list_for_each_entry_rcu(chain, &table->chains, list) {
 			if (__nf_tables_dump_rules(skb, &idx,
-						   cb, table, chain, reset))
+						   cb, table, chain))
 				goto done;
 		}
 
@@ -3578,6 +3575,8 @@ 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;
 
 	cb->data = ctx;
 	return 0;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [nf-next PATCH 4/5] netfilter: nf_tables: Carry s_idx in nft_rule_dump_ctx
  2023-09-29 19:19 [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Phil Sutter
                   ` (2 preceding siblings ...)
  2023-09-29 19:19 ` [nf-next PATCH 3/5] netfilter: nf_tables: Carry reset flag in nft_rule_dump_ctx Phil Sutter
@ 2023-09-29 19:19 ` Phil Sutter
  2023-09-29 19:19 ` [nf-next PATCH 5/5] netfilter: nf_tables: Don't allocate nft_rule_dump_ctx Phil Sutter
  2023-10-05  8:02 ` [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Florian Westphal
  5 siblings, 0 replies; 7+ messages in thread
From: Phil Sutter @ 2023-09-29 19:19 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

In order to move the context into struct netlink_callback's scratch
area, the latter must be unused first.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 net/netfilter/nf_tables_api.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 21dd6a27ca598..a8c8d9d116d56 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3441,6 +3441,7 @@ static void audit_log_rule_reset(const struct nft_table *table,
 }
 
 struct nft_rule_dump_ctx {
+	unsigned int s_idx;
 	char *table;
 	char *chain;
 	bool reset;
@@ -3455,7 +3456,6 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
 	struct nft_rule_dump_ctx *ctx = cb->data;
 	struct net *net = sock_net(skb->sk);
 	const struct nft_rule *rule, *prule;
-	unsigned int s_idx = cb->args[0];
 	unsigned int entries = 0;
 	int ret = 0;
 	u64 handle;
@@ -3464,7 +3464,7 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
 	list_for_each_entry_rcu(rule, &chain->rules, list) {
 		if (!nft_is_active(net, rule))
 			goto cont_skip;
-		if (*idx < s_idx)
+		if (*idx < ctx->s_idx)
 			goto cont;
 		if (prule)
 			handle = prule->handle;
@@ -3498,7 +3498,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 				struct netlink_callback *cb)
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
-	const struct nft_rule_dump_ctx *ctx = cb->data;
+	struct nft_rule_dump_ctx *ctx = cb->data;
 	struct nft_table *table;
 	const struct nft_chain *chain;
 	unsigned int idx = 0;
@@ -3547,7 +3547,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 done:
 	rcu_read_unlock();
 
-	cb->args[0] = idx;
+	ctx->s_idx = idx;
 	return skb->len;
 }
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [nf-next PATCH 5/5] netfilter: nf_tables: Don't allocate nft_rule_dump_ctx
  2023-09-29 19:19 [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Phil Sutter
                   ` (3 preceding siblings ...)
  2023-09-29 19:19 ` [nf-next PATCH 4/5] netfilter: nf_tables: Carry s_idx " Phil Sutter
@ 2023-09-29 19:19 ` Phil Sutter
  2023-10-05  8:02 ` [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Florian Westphal
  5 siblings, 0 replies; 7+ messages in thread
From: Phil Sutter @ 2023-09-29 19:19 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel

Since struct netlink_callback::args is not used by rule dumpers anymore,
use it to hold nft_rule_dump_ctx. Add a build-time check to make sure it
won't ever exceed the available space.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 net/netfilter/nf_tables_api.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index a8c8d9d116d56..ad54df5e0f99a 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3453,7 +3453,7 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
 				  const struct nft_table *table,
 				  const struct nft_chain *chain)
 {
-	struct nft_rule_dump_ctx *ctx = cb->data;
+	struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
 	struct net *net = sock_net(skb->sk);
 	const struct nft_rule *rule, *prule;
 	unsigned int entries = 0;
@@ -3498,7 +3498,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 				struct netlink_callback *cb)
 {
 	const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
-	struct nft_rule_dump_ctx *ctx = cb->data;
+	struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
 	struct nft_table *table;
 	const struct nft_chain *chain;
 	unsigned int idx = 0;
@@ -3553,42 +3553,35 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
 
 static int nf_tables_dump_rules_start(struct netlink_callback *cb)
 {
+	struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
 	const struct nlattr * const *nla = cb->data;
-	struct nft_rule_dump_ctx *ctx = NULL;
 
-	ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
-	if (!ctx)
-		return -ENOMEM;
+	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
 
 	if (nla[NFTA_RULE_TABLE]) {
 		ctx->table = nla_strdup(nla[NFTA_RULE_TABLE], GFP_ATOMIC);
-		if (!ctx->table) {
-			kfree(ctx);
+		if (!ctx->table)
 			return -ENOMEM;
-		}
 	}
 	if (nla[NFTA_RULE_CHAIN]) {
 		ctx->chain = nla_strdup(nla[NFTA_RULE_CHAIN], GFP_ATOMIC);
 		if (!ctx->chain) {
 			kfree(ctx->table);
-			kfree(ctx);
 			return -ENOMEM;
 		}
 	}
 	if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
 		ctx->reset = true;
 
-	cb->data = ctx;
 	return 0;
 }
 
 static int nf_tables_dump_rules_done(struct netlink_callback *cb)
 {
-	struct nft_rule_dump_ctx *ctx = cb->data;
+	struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
 
 	kfree(ctx->table);
 	kfree(ctx->chain);
-	kfree(ctx);
 	return 0;
 }
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback
  2023-09-29 19:19 [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Phil Sutter
                   ` (4 preceding siblings ...)
  2023-09-29 19:19 ` [nf-next PATCH 5/5] netfilter: nf_tables: Don't allocate nft_rule_dump_ctx Phil Sutter
@ 2023-10-05  8:02 ` Florian Westphal
  5 siblings, 0 replies; 7+ messages in thread
From: Florian Westphal @ 2023-10-05  8:02 UTC (permalink / raw)
  To: Phil Sutter; +Cc: Pablo Neira Ayuso, Florian Westphal, netfilter-devel

Phil Sutter <phil@nwl.cc> wrote:
> Struct netlink_callback has a 48byte scratch area for use by dump
> callbacks to keep personal stuff.
> 
> In rule dumps set up by nf_tables_getrule(), this is used only to store
> a cursor into the list of rules being dumped. Other data is allocated
> and the pointer value assigned to struct netlink_callback::data.
> 
> Since the allocated data structure is small and fits into the scratch
> area even after adding some more fields, move it there.
> 
> Patch 1 "simplifies" nf_tables_dump_rules_start() a bit, but actually
> exists only to reduce patch 5's size.
> 
> Patch 2 is more or less fallout: The memset would mess things up after
> this series, but it was pointless in the first place.
> 
> Patches 3 and 4 extend struct nft_rule_dump_ctx and make
> struct netlink_callback's scratch area unused.
> 
> Patch 5 then finally eliminates the allocation.
> 
> All this is early preparation for reset command locking but unrelated
> enough to go alone.

LGTM, I've applied this to nf-next:testing to have the buildbots
check it out.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-10-05 16:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-29 19:19 [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Phil Sutter
2023-09-29 19:19 ` [nf-next PATCH 1/5] netfilter: nf_tables: Always allocate nft_rule_dump_ctx Phil Sutter
2023-09-29 19:19 ` [nf-next PATCH 2/5] netfilter: nf_tables: Drop pointless memset when dumping rules Phil Sutter
2023-09-29 19:19 ` [nf-next PATCH 3/5] netfilter: nf_tables: Carry reset flag in nft_rule_dump_ctx Phil Sutter
2023-09-29 19:19 ` [nf-next PATCH 4/5] netfilter: nf_tables: Carry s_idx " Phil Sutter
2023-09-29 19:19 ` [nf-next PATCH 5/5] netfilter: nf_tables: Don't allocate nft_rule_dump_ctx Phil Sutter
2023-10-05  8:02 ` [nf-next PATCH 0/5] nf_tables: nft_rule_dump_ctx fits into netlink_callback Florian Westphal

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