]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
netlink: Fix leaks in netlink_parse_cmp()
authorPhil Sutter <phil@nwl.cc>
Mon, 20 Jan 2020 13:48:26 +0000 (14:48 +0100)
committerPhil Sutter <phil@nwl.cc>
Wed, 22 Jan 2020 08:01:01 +0000 (09:01 +0100)
This fixes several problems at once:

* Err path would leak expr 'right' in two places and 'left' in one.
* Concat case would leak 'right' by overwriting the pointer. Introduce a
  temporary variable to hold the new pointer.

Fixes: 6377380bc265f ("netlink_delinearize: handle relational and lookup concat expressions")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/netlink_delinearize.c

index 06a0312b9921a13f085ce430cccd6be68eac425a..88dbd5a8ecdf38f150dcad32fdfeb42f08a4adce 100644 (file)
@@ -274,7 +274,7 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx,
 {
        struct nft_data_delinearize nld;
        enum nft_registers sreg;
-       struct expr *expr, *left, *right;
+       struct expr *expr, *left, *right, *tmp;
        enum ops op;
 
        sreg = netlink_parse_register(nle, NFTNL_EXPR_CMP_SREG);
@@ -291,19 +291,26 @@ static void netlink_parse_cmp(struct netlink_parse_ctx *ctx,
 
        if (left->len > right->len &&
            expr_basetype(left) != &string_type) {
-               return netlink_error(ctx, loc, "Relational expression size mismatch");
+               netlink_error(ctx, loc, "Relational expression size mismatch");
+               goto err_free;
        } else if (left->len > 0 && left->len < right->len) {
                expr_free(left);
                left = netlink_parse_concat_expr(ctx, loc, sreg, right->len);
                if (left == NULL)
-                       return;
-               right = netlink_parse_concat_data(ctx, loc, sreg, right->len, right);
-               if (right == NULL)
-                       return;
+                       goto err_free;
+               tmp = netlink_parse_concat_data(ctx, loc, sreg, right->len, right);
+               if (tmp == NULL)
+                       goto err_free;
+               expr_free(right);
+               right = tmp;
        }
 
        expr = relational_expr_alloc(loc, op, left, right);
        ctx->stmt = expr_stmt_alloc(loc, expr);
+       return;
+err_free:
+       expr_free(left);
+       expr_free(right);
 }
 
 static void netlink_parse_lookup(struct netlink_parse_ctx *ctx,