From 48aca2de80a7dd73f8f3a461c7f7ed47b6082766 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 3 Dec 2021 17:07:55 +0100 Subject: iptopt: fix crash with invalid field/type combo % nft describe ip option rr value segmentation fault after this fix, this exits with 'Error: unknown ip option type/field'. Problem is that 'rr' doesn't have a value template, so the template struct is all-zeroes, so we crash when trying to use tmpl->dtype (its NULL). Furthermore, expr_describe tries to print expr->identifier but expr is exthdr, not symbol: ->identifier contains garbage. Signed-off-by: Florian Westphal --- src/expression.c | 8 ++++---- src/ipopt.c | 3 +++ src/parser_bison.y | 4 ++++ tests/shell/testcases/parsing/describe | 7 +++++++ 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100755 tests/shell/testcases/parsing/describe diff --git a/src/expression.c b/src/expression.c index 4c0874fe..f1cca884 100644 --- a/src/expression.c +++ b/src/expression.c @@ -135,12 +135,12 @@ void expr_describe(const struct expr *expr, struct output_ctx *octx) nft_print(octx, "datatype %s (%s)", dtype->name, dtype->desc); len = dtype->size; - } else if (dtype != &invalid_type) { + } else { nft_print(octx, "%s expression, datatype %s (%s)", expr_name(expr), dtype->name, dtype->desc); - } else { - nft_print(octx, "datatype %s is invalid\n", expr->identifier); - return; + + if (dtype == &invalid_type) + return; } if (dtype->basetype != NULL) { diff --git a/src/ipopt.c b/src/ipopt.c index 42ea41cd..67e904ff 100644 --- a/src/ipopt.c +++ b/src/ipopt.c @@ -78,6 +78,9 @@ struct expr *ipopt_expr_alloc(const struct location *loc, uint8_t type, if (!tmpl) return NULL; + if (!tmpl->len) + return NULL; + expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype, BYTEORDER_BIG_ENDIAN, tmpl->len); expr->exthdr.desc = desc; diff --git a/src/parser_bison.y b/src/parser_bison.y index 357850de..16607bb7 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -5332,6 +5332,10 @@ ip_hdr_expr : IP ip_hdr_field close_scope_ip | IP OPTION ip_option_type ip_option_field close_scope_ip { $$ = ipopt_expr_alloc(&@$, $3, $4); + if (!$$) { + erec_queue(error(&@1, "unknown ip option type/field"), state->msgs); + YYERROR; + } } | IP OPTION ip_option_type close_scope_ip { diff --git a/tests/shell/testcases/parsing/describe b/tests/shell/testcases/parsing/describe new file mode 100755 index 00000000..2ee072e8 --- /dev/null +++ b/tests/shell/testcases/parsing/describe @@ -0,0 +1,7 @@ +#!/bin/bash + +errmsg='Error: unknown ip option type/field' + +str=$($NFT describe ip option rr value 2>&1 | head -n 1) + +[ "$str" = "$errmsg" ] && exit 0 -- cgit v1.2.3