]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
iptopt: fix crash with invalid field/type combo
authorFlorian Westphal <fw@strlen.de>
Fri, 3 Dec 2021 16:07:55 +0000 (17:07 +0100)
committerFlorian Westphal <fw@strlen.de>
Tue, 7 Dec 2021 11:23:22 +0000 (12:23 +0100)
% 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 <fw@strlen.de>
src/expression.c
src/ipopt.c
src/parser_bison.y
tests/shell/testcases/parsing/describe [new file with mode: 0755]

index 4c0874fe99500ff81ee2d2761127c574f3f4083c..f1cca8845376da52dc1f8fb2d0c7e8364ff8f89e 100644 (file)
@@ -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) {
index 42ea41cd705b2666a2d12cba5c09940520bdb9ec..67e904ff3d88f5c882fa4fc6f1922861031991ad 100644 (file)
@@ -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;
index 357850dececc52441fb41c74df31370eb4fa30e9..16607bb79bdda99a7c327f7be023c896e71a6352 100644 (file)
@@ -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 (executable)
index 0000000..2ee072e
--- /dev/null
@@ -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