Re: [RFC] nftables 0.9.8 -stable backports

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2023-10-09, at 13:36:23 +0200, Pablo Neira Ayuso wrote:
> Hi Arturo, Jeremy,
> 
> This is a small batch offering fixes for nftables 0.9.8. It only
> includes the fixes for the implicit chain regression in recent
> kernels.
> 
> This is a few dependency patches that are missing in 0.9.8 are
> required:
> 
>         3542e49cf539 ("evaluate: init cmd pointer for new on-stack context")
>         a3ac2527724d ("src: split chain list in table")
>         4e718641397c ("cache: rename chain_htable to cache_chain_ht")
> 
> a3ac2527724d is fixing an issue with the cache that is required by the
> fixes. Then, the backport fixes for the implicit chain regression with
> Linux -stable:
> 
>         3975430b12d9 ("src: expand table command before evaluation")
>         27c753e4a8d4 ("rule: expand standalone chain that contains rules")
>         784597a4ed63 ("rule: add helper function to expand chain rules into commands")
> 
> I tested with tests/shell at the time of the nftables 0.9.8 release
> (*I did not use git HEAD tests/shell as I did for 1.0.6*).
> 
> I have kept back the backport of this patch intentionally:
> 
>         56c90a2dd2eb ("evaluate: expand sets and maps before evaluation")
> 
> this depends on the new src/interval.c code, in 0.9.8 overlap and
> automerge come a later stage and cache is not updated incrementally,
> I tried the tests coming in this patch and it works fine.
> 
> I did run a few more tests with rulesets that I have been collecting
> from people that occasionally send them to me for my personal ruleset
> repo.
> 
> I: results: [OK] 266 [FAILED] 0 [TOTAL] 266
> 
> This has been tested with latest Linux kernel 5.10 -stable.
> 
> I can still run a few more tests, I will get back to you if I find any
> issue.
> 
> Let me know, thanks.

Thanks for this.  I started looking into it, but had not yet identified
the preliminaries needed to get the regression fixes working with 0.9.8,
and I was going to ask you for help.  I'll take a proper look this
evening.

J.

> From 0a39091a75b6255422832126df4cbf73c86845cd Mon Sep 17 00:00:00 2001
> From: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> Date: Thu, 1 Apr 2021 22:18:29 +0200
> Subject: [PATCH nft 0.9.8 1/7] cache: rename chain_htable to cache_chain_ht
> 
> upstream 3542e49cf539ecfcef6ef7c2d4befb7896ade2cd commit.
> 
> Rename the hashtable chain that is used for fast cache lookups.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> ---
>  include/rule.h | 4 ++--
>  src/cache.c    | 6 +++---
>  src/rule.c     | 6 +++---
>  3 files changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/include/rule.h b/include/rule.h
> index 330a09aa77fa..43872db8947a 100644
> --- a/include/rule.h
> +++ b/include/rule.h
> @@ -154,7 +154,7 @@ struct table {
>  	struct handle		handle;
>  	struct location		location;
>  	struct scope		scope;
> -	struct list_head	*chain_htable;
> +	struct list_head	*cache_chain_ht;
>  	struct list_head	chains;
>  	struct list_head	sets;
>  	struct list_head	objs;
> @@ -220,7 +220,7 @@ struct hook_spec {
>   */
>  struct chain {
>  	struct list_head	list;
> -	struct list_head	hlist;
> +	struct list_head	cache_hlist;
>  	struct handle		handle;
>  	struct location		location;
>  	unsigned int		refcnt;
> diff --git a/src/cache.c b/src/cache.c
> index ed2609008e22..7101b74160be 100644
> --- a/src/cache.c
> +++ b/src/cache.c
> @@ -194,7 +194,7 @@ static int chain_cache_cb(struct nftnl_chain *nlc, void *arg)
>  	if (chain->flags & CHAIN_F_BINDING) {
>  		list_add_tail(&chain->list, &ctx->table->chain_bindings);
>  	} else {
> -		list_add_tail(&chain->hlist, &ctx->table->chain_htable[hash]);
> +		list_add_tail(&chain->cache_hlist, &ctx->table->cache_chain_ht[hash]);
>  		list_add_tail(&chain->list, &ctx->table->chains);
>  	}
>  
> @@ -238,7 +238,7 @@ void chain_cache_add(struct chain *chain, struct table *table)
>  	uint32_t hash;
>  
>  	hash = djb_hash(chain->handle.chain.name) % NFT_CACHE_HSIZE;
> -	list_add_tail(&chain->hlist, &table->chain_htable[hash]);
> +	list_add_tail(&chain->cache_hlist, &table->cache_chain_ht[hash]);
>  	list_add_tail(&chain->list, &table->chains);
>  }
>  
> @@ -249,7 +249,7 @@ struct chain *chain_cache_find(const struct table *table,
>  	uint32_t hash;
>  
>  	hash = djb_hash(handle->chain.name) % NFT_CACHE_HSIZE;
> -	list_for_each_entry(chain, &table->chain_htable[hash], hlist) {
> +	list_for_each_entry(chain, &table->cache_chain_ht[hash], cache_hlist) {
>  		if (!strcmp(chain->handle.chain.name, handle->chain.name))
>  			return chain;
>  	}
> diff --git a/src/rule.c b/src/rule.c
> index e4bb6bae276a..3b445851f657 100644
> --- a/src/rule.c
> +++ b/src/rule.c
> @@ -1328,10 +1328,10 @@ struct table *table_alloc(void)
>  	init_list_head(&table->scope.symbols);
>  	table->refcnt = 1;
>  
> -	table->chain_htable =
> +	table->cache_chain_ht =
>  		xmalloc(sizeof(struct list_head) * NFT_CACHE_HSIZE);
>  	for (i = 0; i < NFT_CACHE_HSIZE; i++)
> -		init_list_head(&table->chain_htable[i]);
> +		init_list_head(&table->cache_chain_ht[i]);
>  
>  	return table;
>  }
> @@ -1359,7 +1359,7 @@ void table_free(struct table *table)
>  		obj_free(obj);
>  	handle_free(&table->handle);
>  	scope_release(&table->scope);
> -	xfree(table->chain_htable);
> +	xfree(table->cache_chain_ht);
>  	xfree(table);
>  }
>  
> -- 
> 2.30.2
> 

> From f37e4261130b021edf068e4d5c6ca062ce4e2ac1 Mon Sep 17 00:00:00 2001
> From: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> Date: Thu, 1 Apr 2021 22:19:30 +0200
> Subject: [PATCH nft 0.9.8 2/7] src: split chain list in table
> 
> upstream a3ac2527724dd27628e12caaa55f731b109e4586 commit.
> 
> This patch splits table->lists in two:
> 
> - Chains that reside in the cache are stored in the new
>   tables->cache_chain and tables->cache_chain_ht. The hashtable chain
>   cache allows for fast chain lookups.
> 
> - Chains that defined via command line / ruleset file reside in
>   tables->chains.
> 
> Note that chains in the cache (already in the kernel) are not placed in
> the table->chains.
> 
> By keeping separated lists, chains defined via command line / ruleset
> file can be added to cache.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> ---
>  include/rule.h |  2 ++
>  src/cache.c    |  6 +++---
>  src/json.c     |  6 +++---
>  src/rule.c     | 18 +++++++++++-------
>  4 files changed, 19 insertions(+), 13 deletions(-)
> 
> diff --git a/include/rule.h b/include/rule.h
> index 43872db8947a..dde32367f48f 100644
> --- a/include/rule.h
> +++ b/include/rule.h
> @@ -155,6 +155,7 @@ struct table {
>  	struct location		location;
>  	struct scope		scope;
>  	struct list_head	*cache_chain_ht;
> +	struct list_head	cache_chain;
>  	struct list_head	chains;
>  	struct list_head	sets;
>  	struct list_head	objs;
> @@ -221,6 +222,7 @@ struct hook_spec {
>  struct chain {
>  	struct list_head	list;
>  	struct list_head	cache_hlist;
> +	struct list_head	cache_list;
>  	struct handle		handle;
>  	struct location		location;
>  	unsigned int		refcnt;
> diff --git a/src/cache.c b/src/cache.c
> index 7101b74160be..32e6eea4ac5c 100644
> --- a/src/cache.c
> +++ b/src/cache.c
> @@ -192,10 +192,10 @@ static int chain_cache_cb(struct nftnl_chain *nlc, void *arg)
>  	chain = netlink_delinearize_chain(ctx->nlctx, nlc);
>  
>  	if (chain->flags & CHAIN_F_BINDING) {
> -		list_add_tail(&chain->list, &ctx->table->chain_bindings);
> +		list_add_tail(&chain->cache_list, &ctx->table->chain_bindings);
>  	} else {
>  		list_add_tail(&chain->cache_hlist, &ctx->table->cache_chain_ht[hash]);
> -		list_add_tail(&chain->list, &ctx->table->chains);
> +		list_add_tail(&chain->cache_list, &ctx->table->cache_chain);
>  	}
>  
>  	nftnl_chain_list_del(nlc);
> @@ -239,7 +239,7 @@ void chain_cache_add(struct chain *chain, struct table *table)
>  
>  	hash = djb_hash(chain->handle.chain.name) % NFT_CACHE_HSIZE;
>  	list_add_tail(&chain->cache_hlist, &table->cache_chain_ht[hash]);
> -	list_add_tail(&chain->list, &table->chains);
> +	list_add_tail(&chain->cache_list, &table->cache_chain);
>  }
>  
>  struct chain *chain_cache_find(const struct table *table,
> diff --git a/src/json.c b/src/json.c
> index 585d35326ac0..737e73b08b5a 100644
> --- a/src/json.c
> +++ b/src/json.c
> @@ -1594,7 +1594,7 @@ static json_t *table_print_json_full(struct netlink_ctx *ctx,
>  		tmp = flowtable_print_json(flowtable);
>  		json_array_append_new(root, tmp);
>  	}
> -	list_for_each_entry(chain, &table->chains, list) {
> +	list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  		tmp = chain_print_json(chain);
>  		json_array_append_new(root, tmp);
>  
> @@ -1656,7 +1656,7 @@ static json_t *do_list_chain_json(struct netlink_ctx *ctx,
>  	struct chain *chain;
>  	struct rule *rule;
>  
> -	list_for_each_entry(chain, &table->chains, list) {
> +	list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  		if (chain->handle.family != cmd->handle.family ||
>  		    strcmp(cmd->handle.chain.name, chain->handle.chain.name))
>  			continue;
> @@ -1684,7 +1684,7 @@ static json_t *do_list_chains_json(struct netlink_ctx *ctx, struct cmd *cmd)
>  		    cmd->handle.family != table->handle.family)
>  			continue;
>  
> -		list_for_each_entry(chain, &table->chains, list) {
> +		list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  			json_t *tmp = chain_print_json(chain);
>  
>  			json_array_append_new(root, tmp);
> diff --git a/src/rule.c b/src/rule.c
> index 3b445851f657..f76c27c9d091 100644
> --- a/src/rule.c
> +++ b/src/rule.c
> @@ -953,7 +953,7 @@ struct chain *chain_lookup(const struct table *table, const struct handle *h)
>  {
>  	struct chain *chain;
>  
> -	list_for_each_entry(chain, &table->chains, list) {
> +	list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  		if (!strcmp(chain->handle.chain.name, h->chain.name))
>  			return chain;
>  	}
> @@ -965,7 +965,7 @@ struct chain *chain_binding_lookup(const struct table *table,
>  {
>  	struct chain *chain;
>  
> -	list_for_each_entry(chain, &table->chain_bindings, list) {
> +	list_for_each_entry(chain, &table->chain_bindings, cache_list) {
>  		if (!strcmp(chain->handle.chain.name, chain_name))
>  			return chain;
>  	}
> @@ -983,7 +983,7 @@ struct chain *chain_lookup_fuzzy(const struct handle *h,
>  	string_misspell_init(&st);
>  
>  	list_for_each_entry(table, &cache->list, list) {
> -		list_for_each_entry(chain, &table->chains, list) {
> +		list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  			if (!strcmp(chain->handle.chain.name, h->chain.name)) {
>  				*t = table;
>  				return chain;
> @@ -1321,6 +1321,7 @@ struct table *table_alloc(void)
>  
>  	table = xzalloc(sizeof(*table));
>  	init_list_head(&table->chains);
> +	init_list_head(&table->cache_chain);
>  	init_list_head(&table->sets);
>  	init_list_head(&table->objs);
>  	init_list_head(&table->flowtables);
> @@ -1349,7 +1350,10 @@ void table_free(struct table *table)
>  		xfree(table->comment);
>  	list_for_each_entry_safe(chain, next, &table->chains, list)
>  		chain_free(chain);
> -	list_for_each_entry_safe(chain, next, &table->chain_bindings, list)
> +	list_for_each_entry_safe(chain, next, &table->chain_bindings, cache_list)
> +		chain_free(chain);
> +	/* this is implicitly releasing chains in the hashtable cache */
> +	list_for_each_entry_safe(chain, next, &table->cache_chain, cache_list)
>  		chain_free(chain);
>  	list_for_each_entry_safe(set, nset, &table->sets, list)
>  		set_free(set);
> @@ -1465,7 +1469,7 @@ static void table_print(const struct table *table, struct output_ctx *octx)
>  		flowtable_print(flowtable, octx);
>  		delim = "\n";
>  	}
> -	list_for_each_entry(chain, &table->chains, list) {
> +	list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  		nft_print(octx, "%s", delim);
>  		chain_print(chain, octx);
>  		delim = "\n";
> @@ -2555,7 +2559,7 @@ static int do_list_chain(struct netlink_ctx *ctx, struct cmd *cmd,
>  
>  	table_print_declaration(table, &ctx->nft->output);
>  
> -	list_for_each_entry(chain, &table->chains, list) {
> +	list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  		if (chain->handle.family != cmd->handle.family ||
>  		    strcmp(cmd->handle.chain.name, chain->handle.chain.name) != 0)
>  			continue;
> @@ -2580,7 +2584,7 @@ static int do_list_chains(struct netlink_ctx *ctx, struct cmd *cmd)
>  
>  		table_print_declaration(table, &ctx->nft->output);
>  
> -		list_for_each_entry(chain, &table->chains, list) {
> +		list_for_each_entry(chain, &table->cache_chain, cache_list) {
>  			chain_print_declaration(chain, &ctx->nft->output);
>  			nft_print(&ctx->nft->output, "\t}\n");
>  		}
> -- 
> 2.30.2
> 

> From 5af65a30a12396281c751e635509ab1d9363f4bc Mon Sep 17 00:00:00 2001
> From: Florian Westphal <fw@xxxxxxxxx>
> Date: Fri, 4 Mar 2022 11:30:55 +0100
> Subject: [PATCH nft 0.9.8 3/7] evaluate: init cmd pointer for new on-stack
>  context
> 
> upstream 4e718641397c876315a87db441afc53139863122 commit
> 
> else, this will segfault when trying to print the
> "table 'x' doesn't exist" error message.
> 
> Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
> ---
>  src/evaluate.c                                   | 1 +
>  tests/shell/testcases/chains/0041chain_binding_0 | 6 ++++++
>  2 files changed, 7 insertions(+)
> 
> diff --git a/src/evaluate.c b/src/evaluate.c
> index c830dcdbd965..f546667131e1 100644
> --- a/src/evaluate.c
> +++ b/src/evaluate.c
> @@ -3211,6 +3211,7 @@ static int stmt_evaluate_chain(struct eval_ctx *ctx, struct stmt *stmt)
>  			struct eval_ctx rule_ctx = {
>  				.nft	= ctx->nft,
>  				.msgs	= ctx->msgs,
> +				.cmd	= ctx->cmd,
>  			};
>  			struct handle h2 = {};
>  
> diff --git a/tests/shell/testcases/chains/0041chain_binding_0 b/tests/shell/testcases/chains/0041chain_binding_0
> index 59bdbe9f0ba9..4b541bb55c30 100755
> --- a/tests/shell/testcases/chains/0041chain_binding_0
> +++ b/tests/shell/testcases/chains/0041chain_binding_0
> @@ -1,5 +1,11 @@
>  #!/bin/bash
>  
> +# no table x, caused segfault in earlier nft releases
> +$NFT insert rule inet x y handle 107 'goto { log prefix "MOO! "; }'
> +if [ $? -ne 1 ]; then
> +	exit 1
> +fi
> +
>  set -e
>  
>  EXPECTED="table inet x {
> -- 
> 2.30.2
> 

> From 0f559011ee7e805df883be635b88396639fbb87e Mon Sep 17 00:00:00 2001
> From: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> Date: Tue, 12 Sep 2023 23:22:46 +0200
> Subject: [PATCH nft 0.9.8 4/7] rule: add helper function to expand chain rules
>  into commands
> 
> upstream 784597a4ed63b9decb10d74fdb49a1b021e22728 commit.
> 
> This patch adds a helper function to expand chain rules into commands.
> This comes in preparation for the follow up patch.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> ---
>  src/rule.c | 39 ++++++++++++++++++++++-----------------
>  1 file changed, 22 insertions(+), 17 deletions(-)
> 
> diff --git a/src/rule.c b/src/rule.c
> index f76c27c9d091..3fbf4271accd 100644
> --- a/src/rule.c
> +++ b/src/rule.c
> @@ -1503,6 +1503,25 @@ void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc)
>  	cmd->num_attrs++;
>  }
>  
> +static void nft_cmd_expand_chain(struct chain *chain, struct list_head *new_cmds)
> +{
> +	struct rule *rule;
> +	struct handle h;
> +	struct cmd *new;
> +
> +	list_for_each_entry(rule, &chain->rules, list) {
> +		memset(&h, 0, sizeof(h));
> +		handle_merge(&h, &rule->handle);
> +		if (chain->flags & CHAIN_F_BINDING) {
> +			rule->handle.chain_id = chain->handle.chain_id;
> +			rule->handle.chain.location = chain->location;
> +		}
> +		new = cmd_alloc(CMD_ADD, CMD_OBJ_RULE, &h,
> +				&rule->location, rule_get(rule));
> +		list_add_tail(&new->list, new_cmds);
> +	}
> +}
> +
>  void nft_cmd_expand(struct cmd *cmd)
>  {
>  	struct list_head new_cmds;
> @@ -1510,7 +1529,6 @@ void nft_cmd_expand(struct cmd *cmd)
>  	struct flowtable *ft;
>  	struct table *table;
>  	struct chain *chain;
> -	struct rule *rule;
>  	struct obj *obj;
>  	struct cmd *new;
>  	struct handle h;
> @@ -1555,22 +1573,9 @@ void nft_cmd_expand(struct cmd *cmd)
>  					&ft->location, flowtable_get(ft));
>  			list_add_tail(&new->list, &new_cmds);
>  		}
> -		list_for_each_entry(chain, &table->chains, list) {
> -			list_for_each_entry(rule, &chain->rules, list) {
> -				memset(&h, 0, sizeof(h));
> -				handle_merge(&h, &rule->handle);
> -				if (chain->flags & CHAIN_F_BINDING) {
> -					rule->handle.chain_id =
> -						chain->handle.chain_id;
> -					rule->handle.chain.location =
> -						chain->location;
> -				}
> -				new = cmd_alloc(CMD_ADD, CMD_OBJ_RULE, &h,
> -						&rule->location,
> -						rule_get(rule));
> -				list_add_tail(&new->list, &new_cmds);
> -			}
> -		}
> +		list_for_each_entry(chain, &table->chains, list)
> +			nft_cmd_expand_chain(chain, &new_cmds);
> +
>  		list_splice(&new_cmds, &cmd->list);
>  		break;
>  	case CMD_OBJ_SET:
> -- 
> 2.30.2
> 

> From f03bc399d75ef724fcbed184f74fc306ca8ef324 Mon Sep 17 00:00:00 2001
> From: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> Date: Mon, 6 Feb 2023 15:28:41 +0100
> Subject: [PATCH nft 0.9.8 5/7] rule: expand standalone chain that contains
>  rules
> 
> upstream 27c753e4a8d4744f479345e3f5e34cafef751602 commit.
> 
> Otherwise rules that this chain contains are ignored when expressed
> using the following syntax:
> 
> chain inet filter input2 {
>        type filter hook input priority filter; policy accept;
>        ip saddr 1.2.3.4 tcp dport { 22, 443, 123 } drop
> }
> 
> When expanding the chain, remove the rule so the new CMD_OBJ_CHAIN
> case does not expand it again.
> 
> Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1655
> Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> ---
>  src/rule.c                                    | 15 +++++++++---
>  .../testcases/include/0020include_chain_0     | 23 +++++++++++++++++++
>  .../include/dumps/0020include_chain_0.nft     |  6 +++++
>  3 files changed, 41 insertions(+), 3 deletions(-)
>  create mode 100755 tests/shell/testcases/include/0020include_chain_0
>  create mode 100644 tests/shell/testcases/include/dumps/0020include_chain_0.nft
> 
> diff --git a/src/rule.c b/src/rule.c
> index 3fbf4271accd..9139418e1bf8 100644
> --- a/src/rule.c
> +++ b/src/rule.c
> @@ -1505,11 +1505,12 @@ void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc)
>  
>  static void nft_cmd_expand_chain(struct chain *chain, struct list_head *new_cmds)
>  {
> -	struct rule *rule;
> +	struct rule *rule, *next;
>  	struct handle h;
>  	struct cmd *new;
>  
> -	list_for_each_entry(rule, &chain->rules, list) {
> +	list_for_each_entry_safe(rule, next, &chain->rules, list) {
> +		list_del(&rule->list);
>  		memset(&h, 0, sizeof(h));
>  		handle_merge(&h, &rule->handle);
>  		if (chain->flags & CHAIN_F_BINDING) {
> @@ -1517,7 +1518,7 @@ static void nft_cmd_expand_chain(struct chain *chain, struct list_head *new_cmds
>  			rule->handle.chain.location = chain->location;
>  		}
>  		new = cmd_alloc(CMD_ADD, CMD_OBJ_RULE, &h,
> -				&rule->location, rule_get(rule));
> +				&rule->location, rule);
>  		list_add_tail(&new->list, new_cmds);
>  	}
>  }
> @@ -1578,6 +1579,14 @@ void nft_cmd_expand(struct cmd *cmd)
>  
>  		list_splice(&new_cmds, &cmd->list);
>  		break;
> +	case CMD_OBJ_CHAIN:
> +		chain = cmd->chain;
> +		if (!chain || list_empty(&chain->rules))
> +			break;
> +
> +		nft_cmd_expand_chain(chain, &new_cmds);
> +		list_splice(&new_cmds, &cmd->list);
> +		break;
>  	case CMD_OBJ_SET:
>  	case CMD_OBJ_MAP:
>  		set = cmd->set;
> diff --git a/tests/shell/testcases/include/0020include_chain_0 b/tests/shell/testcases/include/0020include_chain_0
> new file mode 100755
> index 000000000000..2ff83c92fda8
> --- /dev/null
> +++ b/tests/shell/testcases/include/0020include_chain_0
> @@ -0,0 +1,23 @@
> +#!/bin/bash
> +
> +set -e
> +
> +tmpfile1=$(mktemp -p .)
> +if [ ! -w $tmpfile1 ] ; then
> +	echo "Failed to create tmp file" >&2
> +	exit 0
> +fi
> +
> +trap "rm -rf $tmpfile1" EXIT # cleanup if aborted
> +
> +RULESET="table inet filter { }
> +include \"$tmpfile1\""
> +
> +RULESET2="chain inet filter input2 {
> +	type filter hook input priority filter; policy accept;
> +	ip saddr 1.2.3.4 tcp dport { 22, 443, 123 } drop
> +}"
> +
> +echo "$RULESET2" > $tmpfile1
> +
> +$NFT -f - <<< $RULESET
> diff --git a/tests/shell/testcases/include/dumps/0020include_chain_0.nft b/tests/shell/testcases/include/dumps/0020include_chain_0.nft
> new file mode 100644
> index 000000000000..3ad6db14d2f5
> --- /dev/null
> +++ b/tests/shell/testcases/include/dumps/0020include_chain_0.nft
> @@ -0,0 +1,6 @@
> +table inet filter {
> +	chain input2 {
> +		type filter hook input priority filter; policy accept;
> +		ip saddr 1.2.3.4 tcp dport { 22, 123, 443 } drop
> +	}
> +}
> -- 
> 2.30.2
> 

> From 050e0b7a85016b733e1a59285df501d1c05eec0b Mon Sep 17 00:00:00 2001
> From: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> Date: Tue, 12 Sep 2023 23:25:27 +0200
> Subject: [PATCH nft 0.9.8 6/7] src: expand table command before evaluation
> 
> upstream 3975430b12d97c92cdf03753342f2269153d5624 commit.
> 
> The nested syntax notation results in one single table command which
> includes all other objects. This differs from the flat notation where
> there is usually one command per object.
> 
> This patch adds a previous step to the evaluation phase to expand the
> objects that are contained in the table into independent commands, so
> both notations have similar representations.
> 
> Remove the code to evaluate the nested representation in the evaluation
> phase since commands are independently evaluated after the expansion.
> 
> The commands are expanded after the set element collapse step, in case
> that there is a long list of singleton element commands to be added to
> the set, to shorten the command list iteration.
> 
> This approach also avoids interference with the object cache that is
> populated in the evaluation, which might refer to objects coming in the
> existing command list that is being processed.
> 
> There is still a post_expand phase to detach the elements from the set
> which could be consolidated by updating the evaluation step to handle
> the CMD_OBJ_SETELEMS command type.
> 
> This patch fixes 27c753e4a8d4 ("rule: expand standalone chain that
> contains rules") which broke rule addition/insertion by index because
> the expansion code after the evaluation messes up the cache.
> 
> Fixes: 27c753e4a8d4 ("rule: expand standalone chain that contains rules")
> Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
> ---
>  include/rule.h    |  1 +
>  src/evaluate.c    | 39 ---------------------------------------
>  src/libnftables.c |  9 ++++++++-
>  src/rule.c        | 21 +++++++++++++++++++--
>  4 files changed, 28 insertions(+), 42 deletions(-)
> 
> diff --git a/include/rule.h b/include/rule.h
> index dde32367f48f..f880cfd32bd8 100644
> --- a/include/rule.h
> +++ b/include/rule.h
> @@ -717,6 +717,7 @@ extern struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
>  			     const struct handle *h, const struct location *loc,
>  			     void *data);
>  extern void nft_cmd_expand(struct cmd *cmd);
> +extern void nft_cmd_post_expand(struct cmd *cmd);
>  extern struct cmd *cmd_alloc_obj_ct(enum cmd_ops op, int type,
>  				    const struct handle *h,
>  				    const struct location *loc, struct obj *obj);
> diff --git a/src/evaluate.c b/src/evaluate.c
> index f546667131e1..232ae39020cc 100644
> --- a/src/evaluate.c
> +++ b/src/evaluate.c
> @@ -4068,7 +4068,6 @@ static uint32_t str2hooknum(uint32_t family, const char *hook)
>  static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain)
>  {
>  	struct table *table;
> -	struct rule *rule;
>  
>  	table = table_lookup_global(ctx);
>  	if (table == NULL)
> @@ -4122,11 +4121,6 @@ static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain)
>  		}
>  	}
>  
> -	list_for_each_entry(rule, &chain->rules, list) {
> -		handle_merge(&rule->handle, &chain->handle);
> -		if (rule_evaluate(ctx, rule, CMD_INVALID) < 0)
> -			return -1;
> -	}
>  	return 0;
>  }
>  
> @@ -4183,11 +4177,6 @@ static int obj_evaluate(struct eval_ctx *ctx, struct obj *obj)
>  
>  static int table_evaluate(struct eval_ctx *ctx, struct table *table)
>  {
> -	struct flowtable *ft;
> -	struct chain *chain;
> -	struct set *set;
> -	struct obj *obj;
> -
>  	if (table_lookup(&ctx->cmd->handle, &ctx->nft->cache) == NULL) {
>  		if (table == NULL) {
>  			table = table_alloc();
> @@ -4198,34 +4187,6 @@ static int table_evaluate(struct eval_ctx *ctx, struct table *table)
>  		}
>  	}
>  
> -	if (ctx->cmd->table == NULL)
> -		return 0;
> -
> -	ctx->table = table;
> -	list_for_each_entry(set, &table->sets, list) {
> -		expr_set_context(&ctx->ectx, NULL, 0);
> -		handle_merge(&set->handle, &table->handle);
> -		if (set_evaluate(ctx, set) < 0)
> -			return -1;
> -	}
> -	list_for_each_entry(chain, &table->chains, list) {
> -		handle_merge(&chain->handle, &table->handle);
> -		ctx->cmd->handle.chain.location = chain->location;
> -		if (chain_evaluate(ctx, chain) < 0)
> -			return -1;
> -	}
> -	list_for_each_entry(ft, &table->flowtables, list) {
> -		handle_merge(&ft->handle, &table->handle);
> -		if (flowtable_evaluate(ctx, ft) < 0)
> -			return -1;
> -	}
> -	list_for_each_entry(obj, &table->objs, list) {
> -		handle_merge(&obj->handle, &table->handle);
> -		if (obj_evaluate(ctx, obj) < 0)
> -			return -1;
> -	}
> -
> -	ctx->table = NULL;
>  	return 0;
>  }
>  
> diff --git a/src/libnftables.c b/src/libnftables.c
> index 044365914747..b1f57802b90e 100644
> --- a/src/libnftables.c
> +++ b/src/libnftables.c
> @@ -420,6 +420,13 @@ static int nft_evaluate(struct nft_ctx *nft, struct list_head *msgs,
>  	if (cache_update(nft, flags, msgs) < 0)
>  		return -1;
>  
> +	list_for_each_entry(cmd, cmds, list) {
> +		if (cmd->op != CMD_ADD)
> +			continue;
> +
> +		nft_cmd_expand(cmd);
> +	}
> +
>  	list_for_each_entry(cmd, cmds, list) {
>  		struct eval_ctx ectx = {
>  			.nft	= nft,
> @@ -437,7 +444,7 @@ static int nft_evaluate(struct nft_ctx *nft, struct list_head *msgs,
>  		if (cmd->op != CMD_ADD)
>  			continue;
>  
> -		nft_cmd_expand(cmd);
> +		nft_cmd_post_expand(cmd);
>  	}
>  
>  	return 0;
> diff --git a/src/rule.c b/src/rule.c
> index 9139418e1bf8..9c74b89c1fb1 100644
> --- a/src/rule.c
> +++ b/src/rule.c
> @@ -1511,8 +1511,9 @@ static void nft_cmd_expand_chain(struct chain *chain, struct list_head *new_cmds
>  
>  	list_for_each_entry_safe(rule, next, &chain->rules, list) {
>  		list_del(&rule->list);
> +		handle_merge(&rule->handle, &chain->handle);
>  		memset(&h, 0, sizeof(h));
> -		handle_merge(&h, &rule->handle);
> +		handle_merge(&h, &chain->handle);
>  		if (chain->flags & CHAIN_F_BINDING) {
>  			rule->handle.chain_id = chain->handle.chain_id;
>  			rule->handle.chain.location = chain->location;
> @@ -1526,10 +1527,10 @@ static void nft_cmd_expand_chain(struct chain *chain, struct list_head *new_cmds
>  void nft_cmd_expand(struct cmd *cmd)
>  {
>  	struct list_head new_cmds;
> -	struct set *set, *newset;
>  	struct flowtable *ft;
>  	struct table *table;
>  	struct chain *chain;
> +	struct set *set;
>  	struct obj *obj;
>  	struct cmd *new;
>  	struct handle h;
> @@ -1543,6 +1544,7 @@ void nft_cmd_expand(struct cmd *cmd)
>  			return;
>  
>  		list_for_each_entry(chain, &table->chains, list) {
> +			handle_merge(&chain->handle, &table->handle);
>  			memset(&h, 0, sizeof(h));
>  			handle_merge(&h, &chain->handle);
>  			h.chain_id = chain->handle.chain_id;
> @@ -1587,6 +1589,21 @@ void nft_cmd_expand(struct cmd *cmd)
>  		nft_cmd_expand_chain(chain, &new_cmds);
>  		list_splice(&new_cmds, &cmd->list);
>  		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +void nft_cmd_post_expand(struct cmd *cmd)
> +{
> +	struct list_head new_cmds;
> +	struct set *set, *newset;
> +	struct cmd *new;
> +	struct handle h;
> +
> +	init_list_head(&new_cmds);
> +
> +	switch (cmd->obj) {
>  	case CMD_OBJ_SET:
>  	case CMD_OBJ_MAP:
>  		set = cmd->set;
> -- 
> 2.30.2
> 

> From 69d1ab7c50a6a1dd369b50a5edad769b98779e12 Mon Sep 17 00:00:00 2001
> From: Phil Sutter <phil@xxxxxx>
> Date: Wed, 23 Aug 2023 18:18:49 +0200
> Subject: [PATCH nft 0.9.8 7/7] tests: shell: Stabilize
>  sets/0043concatenated_ranges_0 test
> 
> upstream c791765cb0d62ba261f0b495e07315437b3ae914 commit.
> 
> On a slow system, one of the 'delete element' commands would
> occasionally fail. Assuming it can only happen if the 2s timeout passes
> "too quickly", work around it by adding elements with a 2m timeout
> instead and when wanting to test the element expiry just drop and add
> the element again with a short timeout.
> 
> Fixes: 6231d3fa4af1e ("tests: shell: Fix for unstable sets/0043concatenated_ranges_0")
> Signed-off-by: Phil Sutter <phil@xxxxxx>
> ---
>  tests/shell/testcases/sets/0043concatenated_ranges_0 | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/shell/testcases/sets/0043concatenated_ranges_0 b/tests/shell/testcases/sets/0043concatenated_ranges_0
> index 11767373bcd2..8d3dacf6e38a 100755
> --- a/tests/shell/testcases/sets/0043concatenated_ranges_0
> +++ b/tests/shell/testcases/sets/0043concatenated_ranges_0
> @@ -147,7 +147,7 @@ for ta in ${TYPES}; do
>  			eval add_b=\$ADD_${tb}
>  			eval add_c=\$ADD_${tc}
>  			${NFT} add element inet filter test \
> -				"{ ${add_a} . ${add_b} . ${add_c} timeout 1s${mapv}}"
> +				"{ ${add_a} . ${add_b} . ${add_c} timeout 2m${mapv}}"
>  			[ $(${NFT} list ${setmap} inet filter test |	\
>  			   grep -c "${add_a} . ${add_b} . ${add_c}") -eq 1 ]
>  
> @@ -180,6 +180,10 @@ for ta in ${TYPES}; do
>  				continue
>  			fi
>  
> +			${NFT} delete element inet filter test \
> +				"{ ${add_a} . ${add_b} . ${add_c} ${mapv}}"
> +			${NFT} add element inet filter test \
> +				"{ ${add_a} . ${add_b} . ${add_c} timeout 1s${mapv}}"
>  			sleep 1
>  			[ $(${NFT} list ${setmap} inet filter test |		\
>  			   grep -c "${add_a} . ${add_b} . ${add_c} ${mapv}") -eq 0 ]
> -- 
> 2.30.2
> 

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux