diff options
author | Florian Westphal <fw@strlen.de> | 2023-12-09 00:37:09 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2023-12-11 17:10:33 +0100 |
commit | 08925ba0daf19753df933fed69f4572a7c9d3d47 (patch) | |
tree | 10b219b7d3b3648615c2c171fcd35ffcb5ce9ad7 | |
parent | 5fec559727ffd2c6c8958748beab782096385758 (diff) |
evaluate: validate chain max length
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 <fw@strlen.de>
-rw-r--r-- | src/evaluate.c | 34 | ||||
-rw-r--r-- | tests/shell/testcases/bogons/nft-f/huge_chain_name_assert | 5 | ||||
-rw-r--r-- | tests/shell/testcases/bogons/nft-f/huge_chain_name_define_assert | 7 |
3 files changed, 45 insertions, 1 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index a62a2346..715c398a 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2738,6 +2738,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) { @@ -2763,7 +2792,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: @@ -2964,6 +2993,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 + } +} |