From: Omkhar Arasaratnam Date: Wed, 8 Jul 2026 23:09:52 +0000 (+0000) Subject: parser_json: initialize geneve options list for empty tunnel array X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e052d61a144fc4ad1aa6e68d65993420865fa5cb;p=thirdparty%2Fnftables.git parser_json: initialize geneve options list for empty tunnel array json_parse_cmd_add_object() only initializes obj->tunnel.geneve_opts on the first iteration of the json_array_foreach() loop, guarded by "if (index == 0)". A geneve tunnel object whose options array is empty ("tunnel": []) never enters the loop, so the list head is left uninitialized. obj_tunnel_add_opts() (src/mnl.c) later walks it with list_for_each_entry() and passes the bogus element to libnftnl, which dereferences the near-NULL pointer and crashes nft: # nft -j -f empty_geneve.json AddressSanitizer: SEGV on unknown address 0x000000000012 #1 nftnl_tunnel_opt_geneve_set obj/tunnel.c:880 #2 nftnl_tunnel_opt_set obj/tunnel.c:910 #3 obj_tunnel_add_opts src/mnl.c:1608 #4 mnl_nft_obj_add src/mnl.c:1757 #5 do_command_add src/rule.c:1542 Initialize the list head unconditionally before the loop and drop the per-iteration guard, so an empty array leaves a valid empty list. The equivalent native-syntax empty definition was already handled in commit f9047c1f ("evaluate: tunnel: don't assume src is set"); this covers the JSON parser path, which that fix did not reach. Fixes: 3a957f8f1ff1 ("tunnel: add tunnel object and statement json support") Signed-off-by: Omkhar Arasaratnam Signed-off-by: Florian Westphal --- diff --git a/src/parser_json.c b/src/parser_json.c index f04772a0..6a0c1745 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -3941,6 +3941,8 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, "{s:o}", "tunnel", &tmp_json)) goto err_free_obj; + init_list_head(&obj->tunnel.geneve_opts); + json_array_foreach(tmp_json, index, value) { struct tunnel_geneve *geneve = xmalloc(sizeof(struct tunnel_geneve)); if (!geneve) @@ -3963,9 +3965,6 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, goto err_free_obj; } - if (index == 0) - init_list_head(&obj->tunnel.geneve_opts); - list_add_tail(&geneve->list, &obj->tunnel.geneve_opts); } break; diff --git a/tests/shell/testcases/bogons/nft-j-f/empty_tunnel_option_array b/tests/shell/testcases/bogons/nft-j-f/empty_tunnel_option_array new file mode 100644 index 00000000..9e8afbe7 --- /dev/null +++ b/tests/shell/testcases/bogons/nft-j-f/empty_tunnel_option_array @@ -0,0 +1,5 @@ +{ "nftables": [ + { "add": { "table": { "family": "netdev", "name": "x" } } }, + { "add": { "tunnel": { "family": "netdev", "name": "t", "table": "y", + "src-ipv4": "192.168.2.10", "dst-ipv4": "", + "type": "geneve", "tunnel": [] } } } ] }