Set on CHAIN_F_BASECHAIN when policy is specified in chain, otherwise chain priority is not evaluated. Toggling this flag requires needs two 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. Fixes: acdfae9c3126 ("src: allow to specify the default policy for base chains") Signed-off-by: Pablo Neira Ayuso --- src/evaluate.c | 27 ++++++++++--------- src/mnl.c | 8 ++++-- src/parser_bison.y | 1 + .../bogons/nft-f/basechain_bad_policy | 2 ++ 4 files changed, 24 insertions(+), 14 deletions(-) create mode 100644 tests/shell/testcases/bogons/nft-f/basechain_bad_policy 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 } $0->policy = $2; $0->policy->location = @$; + $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; };}; -- 2.30.2