Included bogon causes a crash because the list head isn't initialised due to tunnel->type == VXLAN. Signed-off-by: Florian Westphal --- src/parser_bison.y | 38 ++++++++++++++++--- .../bogons/nft-f/tunnel_in_tunnel_crash | 10 +++++ 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 tests/shell/testcases/bogons/nft-f/tunnel_in_tunnel_crash diff --git a/src/parser_bison.y b/src/parser_bison.y index 4e028d31c165..3c21c7584d01 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -144,6 +144,19 @@ static bool already_set(const void *attr, const struct location *loc, return true; } +static bool tunnel_set_type(const struct location *loc, + struct obj *obj, enum tunnel_type type, const char *name, + struct parser_state *state) +{ + if (obj->tunnel.type) { + erec_queue(error(loc, "Cannot create new %s section inside another tunnel", name), state->msgs); + return false; + } + + obj->tunnel.type = type; + return true; +} + static struct expr *ifname_expr_alloc(const struct location *location, struct list_head *queue, const char *name) @@ -4980,11 +4993,15 @@ erspan_block : /* empty */ { $$ = $-1; } erspan_block_alloc : /* empty */ { $$ = $-1; + + if (!tunnel_set_type(&$$->location, $$, TUNNEL_ERSPAN, "erspan", state)) + YYERROR; } ; erspan_config : HDRVERSION NUM { + assert($0->tunnel.type == TUNNEL_ERSPAN); $0->tunnel.erspan.version = $2; } | INDEX NUM @@ -5017,6 +5034,10 @@ geneve_block : /* empty */ { $$ = $-1; } geneve_block_alloc : /* empty */ { $$ = $-1; + if (!tunnel_set_type(&$$->location, $$, TUNNEL_GENEVE, "geneve", state)) + YYERROR; + + init_list_head(&$$->tunnel.geneve_opts); } ; @@ -5024,6 +5045,8 @@ geneve_config : CLASS NUM OPTTYPE NUM DATA string { struct tunnel_geneve *geneve; + assert($0->tunnel.type == TUNNEL_GENEVE); + geneve = xmalloc(sizeof(struct tunnel_geneve)); geneve->geneve_class = $2; geneve->type = $4; @@ -5034,10 +5057,6 @@ geneve_config : CLASS NUM OPTTYPE NUM DATA string YYERROR; } - if (!$0->tunnel.type) { - $0->tunnel.type = TUNNEL_GENEVE; - init_list_head(&$0->tunnel.geneve_opts); - } list_add_tail(&geneve->list, &$0->tunnel.geneve_opts); free_const($6); } @@ -5055,11 +5074,15 @@ vxlan_block : /* empty */ { $$ = $-1; } vxlan_block_alloc : /* empty */ { $$ = $-1; + + if (!tunnel_set_type(&$$->location, $$, TUNNEL_VXLAN, "vxlan", state)) + YYERROR; } ; vxlan_config : GBP NUM { + assert($0->tunnel.type == TUNNEL_VXLAN); $0->tunnel.vxlan.gbp = $2; } ; @@ -5123,13 +5146,16 @@ tunnel_config : ID NUM } | ERSPAN erspan_block_alloc '{' erspan_block '}' { - $0->tunnel.type = TUNNEL_ERSPAN; + $2->location = @2; } | VXLAN vxlan_block_alloc '{' vxlan_block '}' { - $0->tunnel.type = TUNNEL_VXLAN; + $2->location = @2; } | GENEVE geneve_block_alloc '{' geneve_block '}' + { + $2->location = @2; + } ; tunnel_block : /* empty */ { $$ = $-1; } diff --git a/tests/shell/testcases/bogons/nft-f/tunnel_in_tunnel_crash b/tests/shell/testcases/bogons/nft-f/tunnel_in_tunnel_crash new file mode 100644 index 000000000000..9f029807f521 --- /dev/null +++ b/tests/shell/testcases/bogons/nft-f/tunnel_in_tunnel_crash @@ -0,0 +1,10 @@ +table netdev x { + tunnel geneve-t { + vxlan { + gbp 200 + } + geneve { + class 0x1 opt-type 0x1 data "0x12345678" + } + } + -- 2.51.0