* [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks
@ 2025-03-31 15:23 Florian Westphal
2025-03-31 15:23 ` [PATCH nft 2/2] evaluate: only allow stateful statements in set and map definitions Florian Westphal
2025-03-31 18:02 ` [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks Pablo Neira Ayuso
0 siblings, 2 replies; 5+ messages in thread
From: Florian Westphal @ 2025-03-31 15:23 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
We'll gain another F_STATEFUL check in a followup patch,
so lets condense the pattern into a helper to reduce copypaste.
Signed-off-by: Florian Westphal <fw@strlen.de>
---
src/evaluate.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/evaluate.c b/src/evaluate.c
index e4a7b5ceaafa..e9ab829b6bbb 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3453,6 +3453,17 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
return expr_evaluate(ctx, &stmt->payload.val);
}
+static int stmt_evaluate_stateful(struct eval_ctx *ctx, struct stmt *stmt, const char *name)
+{
+ if (stmt_evaluate(ctx, stmt) < 0)
+ return -1;
+
+ if (!(stmt->flags & STMT_F_STATEFUL))
+ return stmt_error(ctx, stmt, "%s statement must be stateful", name);
+
+ return 0;
+}
+
static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
{
struct expr *key, *setref;
@@ -3526,11 +3537,8 @@ static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
stmt->meter.set = setref;
- if (stmt_evaluate(ctx, stmt->meter.stmt) < 0)
+ if (stmt_evaluate_stateful(ctx, stmt->meter.stmt, "meter") < 0)
return -1;
- if (!(stmt->meter.stmt->flags & STMT_F_STATEFUL))
- return stmt_binary_error(ctx, stmt->meter.stmt, stmt,
- "meter statement must be stateful");
return 0;
}
@@ -4662,11 +4670,8 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
return expr_error(ctx->msgs, stmt->set.key,
"Key expression comments are not supported");
list_for_each_entry(this, &stmt->set.stmt_list, list) {
- if (stmt_evaluate(ctx, this) < 0)
+ if (stmt_evaluate_stateful(ctx, this, "set") < 0)
return -1;
- if (!(this->flags & STMT_F_STATEFUL))
- return stmt_error(ctx, this,
- "statement must be stateful");
}
this_set = stmt->set.set->set;
@@ -4726,11 +4731,8 @@ static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
"Data expression timeouts are not supported");
list_for_each_entry(this, &stmt->map.stmt_list, list) {
- if (stmt_evaluate(ctx, this) < 0)
+ if (stmt_evaluate_stateful(ctx, this, "map") < 0)
return -1;
- if (!(this->flags & STMT_F_STATEFUL))
- return stmt_error(ctx, this,
- "statement must be stateful");
}
return 0;
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH nft 2/2] evaluate: only allow stateful statements in set and map definitions
2025-03-31 15:23 [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks Florian Westphal
@ 2025-03-31 15:23 ` Florian Westphal
2025-03-31 16:15 ` Florian Westphal
2025-03-31 18:02 ` [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks Pablo Neira Ayuso
1 sibling, 1 reply; 5+ messages in thread
From: Florian Westphal @ 2025-03-31 15:23 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
The bison parser doesn't allow this to happen due to grammar
restrictions, but the json input has no such issues.
The bogon input assigns 'notrack' which triggers:
BUG: unknown stateful statement type 19
nft: src/netlink_linearize.c:1061: netlink_gen_stmt_stateful: Assertion `0' failed.
After patch, we get:
Error: map statement must be stateful
Fixes: 07958ec53830 ("json: add set statement list support")
Signed-off-by: Florian Westphal <fw@strlen.de>
---
src/evaluate.c | 5 ++-
.../unkown_stateful_statement_type_19_assert | 34 +++++++++++++++++++
2 files changed, 38 insertions(+), 1 deletion(-)
create mode 100644 tests/shell/testcases/bogons/nft-j-f/unkown_stateful_statement_type_19_assert
diff --git a/src/evaluate.c b/src/evaluate.c
index e9ab829b6bbb..f73edc916406 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -5157,8 +5157,11 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
if (set->timeout)
set->flags |= NFT_SET_TIMEOUT;
- list_for_each_entry(stmt, &set->stmt_list, list)
+ list_for_each_entry(stmt, &set->stmt_list, list) {
+ if (stmt_evaluate_stateful(ctx, stmt,type) < 0)
+ return -1;
num_stmts++;
+ }
if (num_stmts > 1)
set->flags |= NFT_SET_EXPR;
diff --git a/tests/shell/testcases/bogons/nft-j-f/unkown_stateful_statement_type_19_assert b/tests/shell/testcases/bogons/nft-j-f/unkown_stateful_statement_type_19_assert
new file mode 100644
index 000000000000..e8a0f768d754
--- /dev/null
+++ b/tests/shell/testcases/bogons/nft-j-f/unkown_stateful_statement_type_19_assert
@@ -0,0 +1,34 @@
+{
+ "nftables": [
+ {
+ "metainfo": {
+ "version": "VERSION",
+ "release_name": "RELEASE_NAME",
+ "json_schema_version": 1
+ }
+ },
+ {
+ "table": {
+ "family": "ip",
+ "name": "t",
+ "handle": 0
+ }
+ },
+ {
+ "map": {
+ "family": "ip",
+ "name": "m",
+ "table": "t",
+ "type": "ipv4_addr",
+ "handle": 0,
+ "map": "mark",
+ "stmt": [
+ {
+ "notrack": null
+ }
+ ]
+ }
+ }
+ ]
+}
+
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH nft 2/2] evaluate: only allow stateful statements in set and map definitions
2025-03-31 15:23 ` [PATCH nft 2/2] evaluate: only allow stateful statements in set and map definitions Florian Westphal
@ 2025-03-31 16:15 ` Florian Westphal
2025-03-31 16:31 ` Pablo Neira Ayuso
0 siblings, 1 reply; 5+ messages in thread
From: Florian Westphal @ 2025-03-31 16:15 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
Florian Westphal <fw@strlen.de> wrote:
> The bison parser doesn't allow this to happen due to grammar
> restrictions, but the json input has no such issues.
>
> The bogon input assigns 'notrack' which triggers:
> BUG: unknown stateful statement type 19
> nft: src/netlink_linearize.c:1061: netlink_gen_stmt_stateful: Assertion `0' failed.
>
> After patch, we get:
> Error: map statement must be stateful
On the same subject of 'do I fix this in evaluate.c or parser_json.c':
cat bla
table t {
set sc {
type inet_service . ifname
}
chain c {
tcp dport . bla* @sc accept
}
}
nft -f bla
BUG: unknown expression type prefix
nft: src/netlink_linearize.c:914: netlink_gen_expr: Assertion `0' failed.
Aborted (core dumped)
I can either fix this in evaluate.c, or I try to rework both
parser_bison.y and parser_json.c to no longer allow prefix expressions
when specifying the lookup key.
I suspect that fixing it in evaluate.c is going to be a lot simpler.
We can't disable prefixes in concatenations, its valid for set element
keys, but I suspect that we can use recursion counter to figure out if
the concatenation is on the RHS of something else (such as part of
EXPR_SET_ELEM).
I'll work on it tomorrow.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH nft 2/2] evaluate: only allow stateful statements in set and map definitions
2025-03-31 16:15 ` Florian Westphal
@ 2025-03-31 16:31 ` Pablo Neira Ayuso
0 siblings, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2025-03-31 16:31 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
On Mon, Mar 31, 2025 at 06:15:30PM +0200, Florian Westphal wrote:
> Florian Westphal <fw@strlen.de> wrote:
> > The bison parser doesn't allow this to happen due to grammar
> > restrictions, but the json input has no such issues.
> >
> > The bogon input assigns 'notrack' which triggers:
> > BUG: unknown stateful statement type 19
> > nft: src/netlink_linearize.c:1061: netlink_gen_stmt_stateful: Assertion `0' failed.
> >
> > After patch, we get:
> > Error: map statement must be stateful
>
> On the same subject of 'do I fix this in evaluate.c or parser_json.c':
>
> cat bla
> table t {
> set sc {
> type inet_service . ifname
> }
>
> chain c {
> tcp dport . bla* @sc accept
> }
> }
> nft -f bla
> BUG: unknown expression type prefix
> nft: src/netlink_linearize.c:914: netlink_gen_expr: Assertion `0' failed.
> Aborted (core dumped)
>
> I can either fix this in evaluate.c, or I try to rework both
> parser_bison.y and parser_json.c to no longer allow prefix expressions
> when specifying the lookup key.
It is probably too complex from the parser in this case.
> I suspect that fixing it in evaluate.c is going to be a lot simpler.
I agree.
But for things that are obviously incorrect at parsing stage and that
are simple to reject, like the empty string case for goto/jump in
verdict map, then it is easy to reject early. The json parser already
rejects unexisting/unsupported keys, the parser is already making a
first pass in validating the input.
I don't think it is a matter of picking between validating _only_ from
parser or from evaluation, I think tightening from parser (when
trivial) and evaluation for more complex invalid input is fine.
> We can't disable prefixes in concatenations, its valid for set element
> keys, but I suspect that we can use recursion counter to figure out if
> the concatenation is on the RHS of something else (such as part of
> EXPR_SET_ELEM).
>
> I'll work on it tomorrow.
Thanks!
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks
2025-03-31 15:23 [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks Florian Westphal
2025-03-31 15:23 ` [PATCH nft 2/2] evaluate: only allow stateful statements in set and map definitions Florian Westphal
@ 2025-03-31 18:02 ` Pablo Neira Ayuso
1 sibling, 0 replies; 5+ messages in thread
From: Pablo Neira Ayuso @ 2025-03-31 18:02 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
On Mon, Mar 31, 2025 at 05:23:19PM +0200, Florian Westphal wrote:
> We'll gain another F_STATEFUL check in a followup patch,
> so lets condense the pattern into a helper to reduce copypaste.
This series LGTM, thanks Florian.
> Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
> src/evaluate.c | 26 ++++++++++++++------------
> 1 file changed, 14 insertions(+), 12 deletions(-)
>
> diff --git a/src/evaluate.c b/src/evaluate.c
> index e4a7b5ceaafa..e9ab829b6bbb 100644
> --- a/src/evaluate.c
> +++ b/src/evaluate.c
> @@ -3453,6 +3453,17 @@ static int stmt_evaluate_payload(struct eval_ctx *ctx, struct stmt *stmt)
> return expr_evaluate(ctx, &stmt->payload.val);
> }
>
> +static int stmt_evaluate_stateful(struct eval_ctx *ctx, struct stmt *stmt, const char *name)
> +{
> + if (stmt_evaluate(ctx, stmt) < 0)
> + return -1;
> +
> + if (!(stmt->flags & STMT_F_STATEFUL))
> + return stmt_error(ctx, stmt, "%s statement must be stateful", name);
> +
> + return 0;
> +}
> +
> static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
> {
> struct expr *key, *setref;
> @@ -3526,11 +3537,8 @@ static int stmt_evaluate_meter(struct eval_ctx *ctx, struct stmt *stmt)
>
> stmt->meter.set = setref;
>
> - if (stmt_evaluate(ctx, stmt->meter.stmt) < 0)
> + if (stmt_evaluate_stateful(ctx, stmt->meter.stmt, "meter") < 0)
> return -1;
> - if (!(stmt->meter.stmt->flags & STMT_F_STATEFUL))
> - return stmt_binary_error(ctx, stmt->meter.stmt, stmt,
> - "meter statement must be stateful");
>
> return 0;
> }
> @@ -4662,11 +4670,8 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, struct stmt *stmt)
> return expr_error(ctx->msgs, stmt->set.key,
> "Key expression comments are not supported");
> list_for_each_entry(this, &stmt->set.stmt_list, list) {
> - if (stmt_evaluate(ctx, this) < 0)
> + if (stmt_evaluate_stateful(ctx, this, "set") < 0)
> return -1;
> - if (!(this->flags & STMT_F_STATEFUL))
> - return stmt_error(ctx, this,
> - "statement must be stateful");
> }
>
> this_set = stmt->set.set->set;
> @@ -4726,11 +4731,8 @@ static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
> "Data expression timeouts are not supported");
>
> list_for_each_entry(this, &stmt->map.stmt_list, list) {
> - if (stmt_evaluate(ctx, this) < 0)
> + if (stmt_evaluate_stateful(ctx, this, "map") < 0)
> return -1;
> - if (!(this->flags & STMT_F_STATEFUL))
> - return stmt_error(ctx, this,
> - "statement must be stateful");
> }
>
> return 0;
> --
> 2.49.0
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-03-31 18:02 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-31 15:23 [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks Florian Westphal
2025-03-31 15:23 ` [PATCH nft 2/2] evaluate: only allow stateful statements in set and map definitions Florian Westphal
2025-03-31 16:15 ` Florian Westphal
2025-03-31 16:31 ` Pablo Neira Ayuso
2025-03-31 18:02 ` [PATCH nft 1/2] evaluate: compact STMT_F_STATEFUL checks Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).