All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gergely Palotas <palotasgergely@gmail.com>
To: netfilter-devel@vger.kernel.org
Cc: Gergely Palotas <palotasgergely@gmail.com>
Subject: [nft PATCH 1/2] parser_json: fix CMD_OBJ/NFT_OBJECT mismatch in delete path
Date: Tue, 11 Aug 2026 15:43:25 +0200	[thread overview]
Message-ID: <20260811134326.300827-2-palotasgergely@gmail.com> (raw)
In-Reply-To: <20260811134326.300827-1-palotasgergely@gmail.com>

The dispatch tables in json_parse_cmd_add() and json_parse_cmd_list()
pass NFT_OBJECT_CT_TIMEOUT, NFT_OBJECT_CT_EXPECT and NFT_OBJECT_TUNNEL
(kernel constants from <linux/netfilter/nf_tables.h>) as the cmd_obj
argument to json_parse_cmd_add_object(), which declares its parameter
as enum cmd_obj.

On the delete/list/destroy early-return path, cmd_obj is forwarded
directly to cmd_alloc(), which expects enum cmd_obj values. For ct
timeout, NFT_OBJECT_CT_TIMEOUT=7 aliases to CMD_OBJ_CHAIN=7, so a
JSON delete of a ct timeout is sent to the kernel as a delete chain
netlink message, returning EINVAL. The same mismatch affects ct
expectation and tunnel objects.

The add path was unaffected because the switch/case blocks inside the
function also used NFT_OBJECT_* constants and contained explicit
cmd_obj = CMD_OBJ_* assignments before falling through to cmd_alloc().
Those assignments are never reached on the delete path due to the
early return.

Fix this by using CMD_OBJ_* constants consistently in the dispatch
tables, matching the declared type of the parameter. Update the
switch cases and the CT_HELPER identity checks in the function
prologue to use CMD_OBJ_* as well, and drop the now-unnecessary
cmd_obj reassignments inside each case.

Signed-off-by: Gergely Palotas <palotasgergely@gmail.com>
---
 src/parser_json.c | 34 +++++++++++++++-------------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/src/parser_json.c b/src/parser_json.c
index e0144b9b..6f40f8d8 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -3792,11 +3792,11 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
 			    "table", &h.table.name))
 		return NULL;
 	if ((op != CMD_DELETE ||
-	     cmd_obj == NFT_OBJECT_CT_HELPER) &&
+	     cmd_obj == CMD_OBJ_CT_HELPER) &&
 	    json_unpack_err(ctx, root, "{s:s}", "name", &h.obj.name)) {
 		return NULL;
 	} else if ((op == CMD_DELETE || op == CMD_DESTROY) &&
-		   cmd_obj != NFT_OBJECT_CT_HELPER &&
+		   cmd_obj != CMD_OBJ_CT_HELPER &&
 		   json_unpack(root, "{s:s}", "name", &h.obj.name) &&
 		   json_unpack(root, "{s:I}", "handle", &h.handle.id)) {
 		json_error(ctx, "Either name or handle required to delete an object.");
@@ -3812,7 +3812,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
 		h.obj.name = xstrdup(h.obj.name);
 
 	if (op == CMD_DELETE || op == CMD_LIST || op == CMD_DESTROY) {
-		if (cmd_obj == NFT_OBJECT_CT_HELPER)
+		if (cmd_obj == CMD_OBJ_CT_HELPER)
 			return cmd_alloc_obj_ct(op, NFT_OBJECT_CT_HELPER,
 						&h, int_loc, obj_alloc(int_loc));
 		return cmd_alloc(op, cmd_obj, &h, int_loc, NULL);
@@ -3849,8 +3849,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
 			}
 		}
 		break;
-	case NFT_OBJECT_CT_HELPER:
-		cmd_obj = CMD_OBJ_CT_HELPER;
+	case CMD_OBJ_CT_HELPER:
 		obj->type = NFT_OBJECT_CT_HELPER;
 		if (!json_unpack(root, "{s:s}", "type", &tmp)) {
 			int ret;
@@ -3881,8 +3880,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
 		}
 		obj->ct_helper.l3proto = l3proto;
 		break;
-	case NFT_OBJECT_CT_TIMEOUT:
-		cmd_obj = CMD_OBJ_CT_TIMEOUT;
+	case CMD_OBJ_CT_TIMEOUT:
 		init_list_head(&obj->ct_timeout.timeout_list);
 		obj->type = NFT_OBJECT_CT_TIMEOUT;
 		if (!json_unpack(root, "{s:s}", "protocol", &tmp)) {
@@ -3905,8 +3903,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
 		if (json_parse_ct_timeout_policy(ctx, root, obj))
 			goto err_free_obj;
 		break;
-	case NFT_OBJECT_CT_EXPECT:
-		cmd_obj = CMD_OBJ_CT_EXPECT;
+	case CMD_OBJ_CT_EXPECT:
 		obj->type = NFT_OBJECT_CT_EXPECT;
 		if (!json_unpack(root, "{s:s}", "l3proto", &tmp) &&
 		    parse_family(tmp, &l3proto)) {
@@ -3972,8 +3969,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
 
 		obj->synproxy.flags |= flags;
 		break;
-	case NFT_OBJECT_TUNNEL:
-		cmd_obj = CMD_OBJ_TUNNEL;
+	case CMD_OBJ_TUNNEL:
 		obj->type = NFT_OBJECT_TUNNEL;
 		if (json_parse_tunnel(ctx, root, obj))
 			goto err_free_obj;
@@ -4011,10 +4007,10 @@ static struct cmd *json_parse_cmd_add(struct json_ctx *ctx,
 		{ "flowtable", CMD_OBJ_FLOWTABLE, json_parse_cmd_add_flowtable },
 		{ "counter", CMD_OBJ_COUNTER, json_parse_cmd_add_object },
 		{ "quota", CMD_OBJ_QUOTA, json_parse_cmd_add_object },
-		{ "ct helper", NFT_OBJECT_CT_HELPER, json_parse_cmd_add_object },
-		{ "ct timeout", NFT_OBJECT_CT_TIMEOUT, json_parse_cmd_add_object },
-		{ "ct expectation", NFT_OBJECT_CT_EXPECT, json_parse_cmd_add_object },
-		{ "tunnel", NFT_OBJECT_TUNNEL, json_parse_cmd_add_object },
+		{ "ct helper", CMD_OBJ_CT_HELPER, json_parse_cmd_add_object },
+		{ "ct timeout", CMD_OBJ_CT_TIMEOUT, json_parse_cmd_add_object },
+		{ "ct expectation", CMD_OBJ_CT_EXPECT, json_parse_cmd_add_object },
+		{ "tunnel", CMD_OBJ_TUNNEL, json_parse_cmd_add_object },
 		{ "limit", CMD_OBJ_LIMIT, json_parse_cmd_add_object },
 		{ "secmark", CMD_OBJ_SECMARK, json_parse_cmd_add_object },
 		{ "synproxy", CMD_OBJ_SYNPROXY, json_parse_cmd_add_object }
@@ -4186,11 +4182,11 @@ static struct cmd *json_parse_cmd_list(struct json_ctx *ctx,
 		{ "counters", CMD_OBJ_COUNTERS, json_parse_cmd_list_multiple },
 		{ "quota", CMD_OBJ_QUOTA, json_parse_cmd_add_object },
 		{ "quotas", CMD_OBJ_QUOTAS, json_parse_cmd_list_multiple },
-		{ "ct helper", NFT_OBJECT_CT_HELPER, json_parse_cmd_add_object },
+		{ "ct helper", CMD_OBJ_CT_HELPER, json_parse_cmd_add_object },
 		{ "ct helpers", CMD_OBJ_CT_HELPERS, json_parse_cmd_list_multiple },
-		{ "ct timeout", NFT_OBJECT_CT_TIMEOUT, json_parse_cmd_add_object },
-		{ "ct expectation", NFT_OBJECT_CT_EXPECT, json_parse_cmd_add_object },
-		{ "tunnel", NFT_OBJECT_TUNNEL, json_parse_cmd_add_object },
+		{ "ct timeout", CMD_OBJ_CT_TIMEOUT, json_parse_cmd_add_object },
+		{ "ct expectation", CMD_OBJ_CT_EXPECT, json_parse_cmd_add_object },
+		{ "tunnel", CMD_OBJ_TUNNEL, json_parse_cmd_add_object },
 		{ "tunnels", CMD_OBJ_TUNNELS, json_parse_cmd_list_multiple },
 		{ "limit", CMD_OBJ_LIMIT, json_parse_cmd_add_object },
 		{ "limits", CMD_OBJ_LIMIT, json_parse_cmd_list_multiple },
-- 
2.47.3


  reply	other threads:[~2026-08-11 13:42 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-11 13:43 [nft PATCH 0/2] parser_json: fix JSON delete of ct stateful objects Gergely Palotas
2026-08-11 13:43 ` Gergely Palotas [this message]
2026-08-20 11:48   ` [nft PATCH 1/2] parser_json: fix CMD_OBJ/NFT_OBJECT mismatch in delete path Pablo Neira Ayuso
2026-08-11 13:43 ` [nft PATCH 2/2] tests: shell: add JSON delete test for ct stateful objects Gergely Palotas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260811134326.300827-2-palotasgergely@gmail.com \
    --to=palotasgergely@gmail.com \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.