[PATCH nft,v2] src: ensure chain policy evaluation when specified

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

 



Set on CHAIN_F_BASECHAIN when policy is specified in chain, otherwise
chain priority is not evaluated.

Toggling this flag requires needs three adjustments to work though:

1) chain_evaluate() needs skip evaluation of hook name and priority if
   not specified to allow for updating the default chain policy, e.g.

	chain ip x y { policy accept; }

2) update netlink bytecode generation for chain to skip NFTA_CHAIN_HOOK
   so update path is exercised in the kernel.

3) error reporting needs to check if basechain priority and type is
   set on, otherwise skip further hints.

Fixes: acdfae9c3126 ("src: allow to specify the default policy for base chains")
Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
v2: adjust error reporting path too.

 src/cmd.c                                     |  3 +++
 src/evaluate.c                                | 27 ++++++++++---------
 src/mnl.c                                     |  8 ++++--
 src/parser_bison.y                            |  1 +
 .../bogons/nft-f/basechain_bad_policy         |  2 ++
 .../bogons/nft-f/unexisting_chain_set_policy  |  5 ++++
 6 files changed, 32 insertions(+), 14 deletions(-)
 create mode 100644 tests/shell/testcases/bogons/nft-f/basechain_bad_policy
 create mode 100644 tests/shell/testcases/bogons/nft-f/unexisting_chain_set_policy

diff --git a/src/cmd.c b/src/cmd.c
index ff634af2ac24..9d5544f03c32 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -282,6 +282,9 @@ static int nft_cmd_chain_error(struct netlink_ctx *ctx, struct cmd *cmd,
 		if (!(chain->flags & CHAIN_F_BASECHAIN))
 			break;
 
+		if (!chain->priority.expr || !chain->type.str)
+			break;
+
 		mpz_export_data(&priority, chain->priority.expr->value,
 				BYTEORDER_HOST_ENDIAN, sizeof(int));
 		if (priority <= -200 && !strcmp(chain->type.str, "nat"))
diff --git a/src/evaluate.c b/src/evaluate.c
index 8f037601c45f..7b524b418eb7 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5772,18 +5772,21 @@ static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain)
 	}
 
 	if (chain->flags & CHAIN_F_BASECHAIN) {
-		chain->hook.num = str2hooknum(chain->handle.family,
-					      chain->hook.name);
-		if (chain->hook.num == NF_INET_NUMHOOKS)
-			return __stmt_binary_error(ctx, &chain->hook.loc, NULL,
-						   "The %s family does not support this hook",
-						   family2str(chain->handle.family));
-
-		if (!evaluate_priority(ctx, &chain->priority,
-				       chain->handle.family, chain->hook.num))
-			return __stmt_binary_error(ctx, &chain->priority.loc, NULL,
-						   "invalid priority expression %s in this context.",
-						   expr_name(chain->priority.expr));
+		if (chain->hook.name) {
+			chain->hook.num = str2hooknum(chain->handle.family,
+						      chain->hook.name);
+			if (chain->hook.num == NF_INET_NUMHOOKS)
+				return __stmt_binary_error(ctx, &chain->hook.loc, NULL,
+							   "The %s family does not support this hook",
+							   family2str(chain->handle.family));
+		}
+		if (chain->priority.expr) {
+			if (!evaluate_priority(ctx, &chain->priority,
+					       chain->handle.family, chain->hook.num))
+				return __stmt_binary_error(ctx, &chain->priority.loc, NULL,
+							   "invalid priority expression %s in this context.",
+							   expr_name(chain->priority.expr));
+		}
 		if (chain->policy) {
 			expr_set_context(&ctx->ectx, &policy_type,
 					 NFT_NAME_MAXLEN * BITS_PER_BYTE);
diff --git a/src/mnl.c b/src/mnl.c
index 43229f2498e5..ceb43b06690c 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -897,7 +897,9 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd,
 			mnl_attr_put_strz(nlh, NFTA_CHAIN_TYPE, cmd->chain->type.str);
 		}
 
-		nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_HOOK);
+		if (cmd->chain->type.str ||
+		    (cmd->chain && cmd->chain->dev_expr))
+			nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_HOOK);
 
 		if (cmd->chain->type.str) {
 			mnl_attr_put_u32(nlh, NFTA_HOOK_HOOKNUM, htonl(cmd->chain->hook.num));
@@ -909,7 +911,9 @@ int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd,
 		if (cmd->chain && cmd->chain->dev_expr)
 			mnl_nft_chain_devs_build(nlh, cmd);
 
-		mnl_attr_nest_end(nlh, nest);
+		if (cmd->chain->type.str ||
+		    (cmd->chain && cmd->chain->dev_expr))
+			mnl_attr_nest_end(nlh, nest);
 	}
 
 	nftnl_chain_free(nlc);
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 0b1ea699c610..1e4b3f8a50c5 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2834,6 +2834,7 @@ policy_spec		:	POLICY		policy_expr	close_scope_policy
 				}
 				$<chain>0->policy		= $2;
 				$<chain>0->policy->location	= @$;
+				$<chain>0->flags		|= CHAIN_F_BASECHAIN;
 			}
 			;
 
diff --git a/tests/shell/testcases/bogons/nft-f/basechain_bad_policy b/tests/shell/testcases/bogons/nft-f/basechain_bad_policy
new file mode 100644
index 000000000000..998e423cb7b4
--- /dev/null
+++ b/tests/shell/testcases/bogons/nft-f/basechain_bad_policy
@@ -0,0 +1,2 @@
+define MY_POLICY = deny
+table T { chain C { policy $MY_POLICY; };};
diff --git a/tests/shell/testcases/bogons/nft-f/unexisting_chain_set_policy b/tests/shell/testcases/bogons/nft-f/unexisting_chain_set_policy
new file mode 100644
index 000000000000..088955996490
--- /dev/null
+++ b/tests/shell/testcases/bogons/nft-f/unexisting_chain_set_policy
@@ -0,0 +1,5 @@
+table ip x {
+        chain y {
+                policy drop;
+        }
+}
-- 
2.30.2





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

  Powered by Linux