From 59f4d37074f4fb30110271d6801f0d1bf6b95f0b Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 9 Dec 2023 00:37:09 +0100 Subject: evaluate: validate chain max length commit 08925ba0daf19753df933fed69f4572a7c9d3d47 upstream. The includes test files cause: BUG: chain is too large (257, 256 max)nft: netlink.c:418: netlink_gen_chain: Assertion `0' failed. Error out in evaluation step instead. Signed-off-by: Florian Westphal --- src/evaluate.c | 34 +++++++++++++++++++++- .../testcases/bogons/nft-f/huge_chain_name_assert | 5 ++++ .../bogons/nft-f/huge_chain_name_define_assert | 7 +++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/shell/testcases/bogons/nft-f/huge_chain_name_assert create mode 100644 tests/shell/testcases/bogons/nft-f/huge_chain_name_define_assert diff --git a/src/evaluate.c b/src/evaluate.c index 124b23e5..5d682a7f 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2530,6 +2530,35 @@ static int expr_evaluate_flagcmp(struct eval_ctx *ctx, struct expr **exprp) return expr_evaluate(ctx, exprp); } +static int verdict_validate_chainlen(struct eval_ctx *ctx, + struct expr *chain) +{ + if (chain->len > NFT_CHAIN_MAXNAMELEN * BITS_PER_BYTE) + return expr_error(ctx->msgs, chain, + "chain name too long (%u, max %u)", + chain->len / BITS_PER_BYTE, + NFT_CHAIN_MAXNAMELEN); + + return 0; +} + +static int expr_evaluate_verdict(struct eval_ctx *ctx, struct expr **exprp) +{ + struct expr *expr = *exprp; + + switch (expr->verdict) { + case NFT_GOTO: + case NFT_JUMP: + if (expr->chain->etype == EXPR_VALUE && + verdict_validate_chainlen(ctx, expr->chain)) + return -1; + + break; + } + + return expr_evaluate_primary(ctx, exprp); +} + static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr) { if (ctx->nft->debug_mask & NFT_DEBUG_EVALUATION) { @@ -2555,7 +2584,7 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr) case EXPR_EXTHDR: return expr_evaluate_exthdr(ctx, expr); case EXPR_VERDICT: - return expr_evaluate_primary(ctx, expr); + return expr_evaluate_verdict(ctx, expr); case EXPR_META: return expr_evaluate_meta(ctx, expr); case EXPR_SOCKET: @@ -2747,6 +2776,9 @@ static int stmt_evaluate_verdict(struct eval_ctx *ctx, struct stmt *stmt) return expr_error(ctx->msgs, stmt->expr->chain, "not a value expression"); } + + if (verdict_validate_chainlen(ctx, stmt->expr->chain)) + return -1; } break; case EXPR_MAP: diff --git a/tests/shell/testcases/bogons/nft-f/huge_chain_name_assert b/tests/shell/testcases/bogons/nft-f/huge_chain_name_assert new file mode 100644 index 00000000..161f867d --- /dev/null +++ b/tests/shell/testcases/bogons/nft-f/huge_chain_name_assert @@ -0,0 +1,5 @@ +table inet x { + chain c { + udp length vmap { 1 : goto rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr } + } +} diff --git a/tests/shell/testcases/bogons/nft-f/huge_chain_name_define_assert b/tests/shell/testcases/bogons/nft-f/huge_chain_name_define_assert new file mode 100644 index 00000000..3c2c0d3e --- /dev/null +++ b/tests/shell/testcases/bogons/nft-f/huge_chain_name_define_assert @@ -0,0 +1,7 @@ +define huge = rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr + +table t { + chain d { + jump $huge + } +} -- cgit v1.2.3