From c317e93ed39364c5bf213d158ba4f577b975fa7d Mon Sep 17 00:00:00 2001 From: Andy Lau Date: Tue, 10 Dec 2024 18:43:19 +0800 Subject: [PATCH] backport some patches from upstream --- backport-Zero-ctx-vars-after-freeing-it.patch | 32 +++ backport-catch-wrong-reset-payload.patch | 38 +++ ...ropriately-with-multidevice-in-chain.patch | 202 +++++++++++++ ...ix-crash-in-json_parse_set_stmt_list.patch | 45 +++ ...t-fix-handle-memleak-from-error-path.patch | 272 ++++++++++++++++++ ...-expression-memleaks-from-error-path.patch | 41 +++ nftables.spec | 21 +- 7 files changed, 650 insertions(+), 1 deletion(-) create mode 100644 backport-Zero-ctx-vars-after-freeing-it.patch create mode 100644 backport-catch-wrong-reset-payload.patch create mode 100644 backport-deal-appropriately-with-multidevice-in-chain.patch create mode 100644 backport-fix-crash-in-json_parse_set_stmt_list.patch create mode 100644 backport-fix-handle-memleak-from-error-path.patch create mode 100644 backport-fix-several-expression-memleaks-from-error-path.patch diff --git a/backport-Zero-ctx-vars-after-freeing-it.patch b/backport-Zero-ctx-vars-after-freeing-it.patch new file mode 100644 index 0000000..86b6234 --- /dev/null +++ b/backport-Zero-ctx-vars-after-freeing-it.patch @@ -0,0 +1,32 @@ +From d361be1f8734461e27117f6c569acf2189fcf81e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 3 Sep 2024 17:43:19 +0200 +Subject: [PATCH] libnftables: Zero ctx->vars after freeing it + +Leaving the invalid pointer value in place will cause a double-free when +users call nft_ctx_clear_vars() first, then nft_ctx_free(). Moreover, +nft_ctx_add_var() passes the pointer to mrealloc() and thus assumes it +to be either NULL or valid. + +Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1772 +Fixes: 9edaa6a51eab4 ("src: add --define key=value") +Signed-off-by: Phil Sutter +--- + src/libnftables.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libnftables.c b/src/libnftables.c +index e214abb..6ac6fbd 100644 +--- a/src/libnftables.c ++++ b/src/libnftables.c +@@ -157,6 +157,7 @@ void nft_ctx_clear_vars(struct nft_ctx *ctx) + } + ctx->num_vars = 0; + xfree(ctx->vars); ++ ctx->vars = NULL; + } + + EXPORT_SYMBOL(nft_ctx_add_include_path); +-- +2.43.0 + diff --git a/backport-catch-wrong-reset-payload.patch b/backport-catch-wrong-reset-payload.patch new file mode 100644 index 0000000..35cb09b --- /dev/null +++ b/backport-catch-wrong-reset-payload.patch @@ -0,0 +1,38 @@ +From 22febeea80043f5fe4eb1aa7723da0a0a6953802 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 13 Sep 2023 20:32:37 +0200 +Subject: [PATCH] parser_json: Catch wrong "reset" payload + +The statement happily accepted any valid expression as payload and +assumed it to be a tcpopt expression (actually, a special case of +exthdr). Add a check to make sure this is the case. + +Standard syntax does not provide this flexibility, so no need to have +the check there as well. + +Fixes: 5d837d270d5a8 ("src: add tcp option reset support") +Signed-off-by: Phil Sutter +--- + src/parser_json.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index e8a175de..9532f7be 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -2797,7 +2797,14 @@ static struct stmt *json_parse_optstrip_stmt(struct json_ctx *ctx, + { + struct expr *expr = json_parse_expr(ctx, value); + +- return expr ? optstrip_stmt_alloc(int_loc, expr) : NULL; ++ if (!expr || ++ expr->etype != EXPR_EXTHDR || ++ expr->exthdr.op != NFT_EXTHDR_OP_TCPOPT) { ++ json_error(ctx, "Illegal TCP optstrip argument"); ++ return NULL; ++ } ++ ++ return optstrip_stmt_alloc(int_loc, expr); + } + + static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root) diff --git a/backport-deal-appropriately-with-multidevice-in-chain.patch b/backport-deal-appropriately-with-multidevice-in-chain.patch new file mode 100644 index 0000000..7d39bf4 --- /dev/null +++ b/backport-deal-appropriately-with-multidevice-in-chain.patch @@ -0,0 +1,202 @@ +From 4dfb5b2010917da3f9f11c83931069931a7d6fb3 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Thu, 23 Nov 2023 10:36:50 +0100 +Subject: [PATCH] json: deal appropriately with multidevice in chain + +Chain device support is broken in JSON: listing does not include devices +and parser only deals with one single device. + +Use existing json_parse_flowtable_devs() function, rename it to +json_parse_devs() to parse the device array. + +Use the dev_array that contains the device names (as string) for the +listing. + +Update incorrect .json-nft files in tests/shell. + +Fixes: 3fdc7541fba0 ("src: add multidevice support for netdev chain") +Signed-off-by: Pablo Neira Ayuso +--- + src/json.c | 25 ++++++------- + src/parser_json.c | 91 +++++++++++++++++++++++------------------------ + 2 files changed, 58 insertions(+), 58 deletions(-) + +diff --git a/src/json.c b/src/json.c +index 2270e22..54e446a 100644 +--- a/src/json.c ++++ b/src/json.c +@@ -255,9 +255,8 @@ static json_t *rule_print_json(struct output_ctx *octx, + + static json_t *chain_print_json(const struct chain *chain) + { +- int priority, policy, n = 0; +- struct expr *dev, *expr; +- json_t *root, *tmp; ++ json_t *root, *tmp, *devs = NULL; ++ int priority, policy, i; + + root = json_pack("{s:s, s:s, s:s, s:I}", + "family", family2str(chain->handle.family), +@@ -279,17 +278,19 @@ static json_t *chain_print_json(const struct chain *chain) + chain->hook.num), + "prio", priority, + "policy", chain_policy2str(policy)); +- if (chain->dev_expr) { +- list_for_each_entry(expr, &chain->dev_expr->expressions, list) { +- dev = expr; +- n++; +- } +- } + +- if (n == 1) { +- json_object_set_new(tmp, "dev", +- json_string(dev->identifier)); ++ for (i = 0; i < chain->dev_array_len; i++) { ++ const char *dev = chain->dev_array[i]; ++ if (!devs) ++ devs = json_string(dev); ++ else if (json_is_string(devs)) ++ devs = json_pack("[o, s]", devs, dev); ++ else ++ json_array_append_new(devs, json_string(dev)); + } ++ if (devs) ++ json_object_set_new(root, "dev", devs); ++ + json_object_update(root, tmp); + json_decref(tmp); + } +diff --git a/src/parser_json.c b/src/parser_json.c +index 05018a6..30a8115 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -2947,14 +2947,49 @@ static struct expr *parse_policy(const char *policy) + sizeof(int) * BITS_PER_BYTE, &policy_num); + } + ++static struct expr *json_parse_devs(struct json_ctx *ctx, json_t *root) ++{ ++ struct expr *tmp, *expr = compound_expr_alloc(int_loc, EXPR_LIST); ++ const char *dev; ++ json_t *value; ++ size_t index; ++ ++ if (!json_unpack(root, "s", &dev)) { ++ tmp = constant_expr_alloc(int_loc, &string_type, ++ BYTEORDER_HOST_ENDIAN, ++ strlen(dev) * BITS_PER_BYTE, dev); ++ compound_expr_add(expr, tmp); ++ return expr; ++ } ++ if (!json_is_array(root)) { ++ expr_free(expr); ++ return NULL; ++ } ++ ++ json_array_foreach(root, index, value) { ++ if (json_unpack(value, "s", &dev)) { ++ json_error(ctx, "Invalid device at index %zu.", ++ index); ++ expr_free(expr); ++ return NULL; ++ } ++ tmp = constant_expr_alloc(int_loc, &string_type, ++ BYTEORDER_HOST_ENDIAN, ++ strlen(dev) * BITS_PER_BYTE, dev); ++ compound_expr_add(expr, tmp); ++ } ++ return expr; ++} ++ + static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, + enum cmd_ops op, enum cmd_obj obj) + { + struct handle h = { + .table.location = *int_loc, + }; +- const char *family = "", *policy = "", *type, *hookstr, *name, *comment = NULL; ++ const char *family = "", *policy = "", *type, *hookstr, *comment = NULL; + struct chain *chain = NULL; ++ json_t *devs = NULL; + int prio; + + if (json_unpack_err(ctx, root, "{s:s, s:s}", +@@ -3009,16 +3044,15 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, + return NULL; + } + +- if (!json_unpack(root, "{s:s}", "dev", &name)) { +- struct expr *dev_expr, *expr; ++ json_unpack(root, "{s:o}", "dev", &devs); + +- dev_expr = compound_expr_alloc(int_loc, EXPR_LIST); +- expr = constant_expr_alloc(int_loc, &integer_type, +- BYTEORDER_HOST_ENDIAN, +- strlen(name) * BITS_PER_BYTE, +- name); +- compound_expr_add(dev_expr, expr); +- chain->dev_expr = dev_expr; ++ if (devs) { ++ chain->dev_expr = json_parse_devs(ctx, devs); ++ if (!chain->dev_expr) { ++ json_error(ctx, "Invalid chain dev."); ++ chain_free(chain); ++ return NULL; ++ } + } + + if (!json_unpack(root, "{s:s}", "policy", &policy)) { +@@ -3313,41 +3347,6 @@ static struct cmd *json_parse_cmd_add_element(struct json_ctx *ctx, + return cmd_alloc(op, cmd_obj, &h, int_loc, expr); + } + +-static struct expr *json_parse_flowtable_devs(struct json_ctx *ctx, +- json_t *root) +-{ +- struct expr *tmp, *expr = compound_expr_alloc(int_loc, EXPR_LIST); +- const char *dev; +- json_t *value; +- size_t index; +- +- if (!json_unpack(root, "s", &dev)) { +- tmp = constant_expr_alloc(int_loc, &string_type, +- BYTEORDER_HOST_ENDIAN, +- strlen(dev) * BITS_PER_BYTE, dev); +- compound_expr_add(expr, tmp); +- return expr; +- } +- if (!json_is_array(root)) { +- expr_free(expr); +- return NULL; +- } +- +- json_array_foreach(root, index, value) { +- if (json_unpack(value, "s", &dev)) { +- json_error(ctx, "Invalid flowtable dev at index %zu.", +- index); +- expr_free(expr); +- return NULL; +- } +- tmp = constant_expr_alloc(int_loc, &string_type, +- BYTEORDER_HOST_ENDIAN, +- strlen(dev) * BITS_PER_BYTE, dev); +- compound_expr_add(expr, tmp); +- } +- return expr; +-} +- + static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx, + json_t *root, enum cmd_ops op, + enum cmd_obj cmd_obj) +@@ -3408,7 +3407,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx, + sizeof(int) * BITS_PER_BYTE, &prio); + + if (devs) { +- flowtable->dev_expr = json_parse_flowtable_devs(ctx, devs); ++ flowtable->dev_expr = json_parse_devs(ctx, devs); + if (!flowtable->dev_expr) { + json_error(ctx, "Invalid flowtable dev."); + flowtable_free(flowtable); +-- +2.43.0 + diff --git a/backport-fix-crash-in-json_parse_set_stmt_list.patch b/backport-fix-crash-in-json_parse_set_stmt_list.patch new file mode 100644 index 0000000..4dd3a84 --- /dev/null +++ b/backport-fix-crash-in-json_parse_set_stmt_list.patch @@ -0,0 +1,45 @@ +From 26d9cbefb10e6bc3765df7e9e7a4fc3b951a80f3 Mon Sep 17 00:00:00 2001 +From: "Sebastian Walz (sivizius)" +Date: Tue, 20 Aug 2024 00:09:26 +0200 +Subject: [PATCH] parser_json: fix crash in json_parse_set_stmt_list + +Due to missing `NULL`-check, there will be a segfault for invalid statements. + +Fixes: 07958ec53830 ("json: add set statement list support") +Signed-off-by: Sebastian Walz (sivizius) +Signed-off-by: Pablo Neira Ayuso +--- + src/parser_json.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index d18188d8..bbe3b1c5 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -2380,7 +2380,7 @@ static void json_parse_set_stmt_list(struct json_ctx *ctx, + json_t *stmt_json) + { + struct list_head *head; +- struct stmt *tmp; ++ struct stmt *stmt; + json_t *value; + size_t index; + +@@ -2392,9 +2392,14 @@ static void json_parse_set_stmt_list(struct json_ctx *ctx, + + head = stmt_list; + json_array_foreach(stmt_json, index, value) { +- tmp = json_parse_stmt(ctx, value); +- list_add(&tmp->list, head); +- head = &tmp->list; ++ stmt = json_parse_stmt(ctx, value); ++ if (!stmt) { ++ json_error(ctx, "Parsing set statements array at index %zd failed.", index); ++ stmt_list_free(stmt_list); ++ return; ++ } ++ list_add(&stmt->list, head); ++ head = &stmt->list; + } + } + diff --git a/backport-fix-handle-memleak-from-error-path.patch b/backport-fix-handle-memleak-from-error-path.patch new file mode 100644 index 0000000..ea7847a --- /dev/null +++ b/backport-fix-handle-memleak-from-error-path.patch @@ -0,0 +1,272 @@ +From 47e18c0eba51a538e1110322d1a9248b0501d7c8 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Mon, 19 Aug 2024 21:34:49 +0200 +Subject: [PATCH] parser_json: fix handle memleak from error path + +Based on patch from Sebastian Walz. + +Fixes: 586ad210368b ("libnftables: Implement JSON parser") +Signed-off-by: Pablo Neira Ayuso +--- + src/parser_json.c | 93 ++++++++++++++++++++++++----------------------- + 1 file changed, 47 insertions(+), 46 deletions(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index 30a8115..cb30d4b 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -3040,8 +3040,7 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, + chain->hook.name = chain_hookname_lookup(hookstr); + if (!chain->hook.name) { + json_error(ctx, "Invalid chain hook '%s'.", hookstr); +- chain_free(chain); +- return NULL; ++ goto err_free_chain; + } + + json_unpack(root, "{s:o}", "dev", &devs); +@@ -3050,8 +3049,7 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, + chain->dev_expr = json_parse_devs(ctx, devs); + if (!chain->dev_expr) { + json_error(ctx, "Invalid chain dev."); +- chain_free(chain); +- return NULL; ++ goto err_free_chain; + } + } + +@@ -3059,8 +3057,7 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, + chain->policy = parse_policy(policy); + if (!chain->policy) { + json_error(ctx, "Unknown policy '%s'.", policy); +- chain_free(chain); +- return NULL; ++ goto err_free_chain; + } + } + +@@ -3069,6 +3066,11 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, + + handle_merge(&chain->handle, &h); + return cmd_alloc(op, obj, &h, int_loc, chain); ++ ++err_free_chain: ++ chain_free(chain); ++ handle_free(&h); ++ return NULL; + } + + static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root, +@@ -3108,6 +3110,7 @@ static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root, + + if (!json_is_array(tmp)) { + json_error(ctx, "Value of property \"expr\" must be an array."); ++ handle_free(&h); + return NULL; + } + +@@ -3127,16 +3130,14 @@ static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root, + if (!json_is_object(value)) { + json_error(ctx, "Unexpected expr array element of type %s, expected object.", + json_typename(value)); +- rule_free(rule); +- return NULL; ++ goto err_free_rule; + } + + stmt = json_parse_stmt(ctx, value); + + if (!stmt) { + json_error(ctx, "Parsing expr array at index %zd failed.", index); +- rule_free(rule); +- return NULL; ++ goto err_free_rule; + } + + rule_stmt_append(rule, stmt); +@@ -3146,6 +3147,11 @@ static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root, + json_object_del(root, "handle"); + + return cmd_alloc(op, obj, &h, int_loc, rule); ++ ++err_free_rule: ++ rule_free(rule); ++ handle_free(&h); ++ return NULL; + } + + static int string_to_nft_object(const char *str) +@@ -3519,8 +3525,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + if (ret < 0 || ret >= (int)sizeof(obj->secmark.ctx)) { + json_error(ctx, "Invalid secmark context '%s', max length is %zu.", + tmp, sizeof(obj->secmark.ctx)); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + } + break; +@@ -3536,8 +3541,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + ret >= (int)sizeof(obj->ct_helper.name)) { + json_error(ctx, "Invalid CT helper type '%s', max length is %zu.", + tmp, sizeof(obj->ct_helper.name)); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + } + if (!json_unpack(root, "{s:s}", "protocol", &tmp)) { +@@ -3547,15 +3551,13 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + obj->ct_helper.l4proto = IPPROTO_UDP; + } else { + json_error(ctx, "Invalid ct helper protocol '%s'.", tmp); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + } + if (!json_unpack(root, "{s:s}", "l3proto", &tmp) && + parse_family(tmp, &l3proto)) { + json_error(ctx, "Invalid ct helper l3proto '%s'.", tmp); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + obj->ct_helper.l3proto = l3proto; + break; +@@ -3569,23 +3571,19 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + obj->ct_timeout.l4proto = IPPROTO_UDP; + } else { + json_error(ctx, "Invalid ct timeout protocol '%s'.", tmp); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + } + if (!json_unpack(root, "{s:s}", "l3proto", &tmp) && + parse_family(tmp, &l3proto)) { + json_error(ctx, "Invalid ct timeout l3proto '%s'.", tmp); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + obj->ct_timeout.l3proto = l3proto; + + init_list_head(&obj->ct_timeout.timeout_list); +- if (json_parse_ct_timeout_policy(ctx, root, obj)) { +- obj_free(obj); +- return NULL; +- } ++ if (json_parse_ct_timeout_policy(ctx, root, obj)) ++ goto err_free_obj; + break; + case NFT_OBJECT_CT_EXPECT: + cmd_obj = CMD_OBJ_CT_EXPECT; +@@ -3593,8 +3591,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + if (!json_unpack(root, "{s:s}", "l3proto", &tmp) && + parse_family(tmp, &l3proto)) { + json_error(ctx, "Invalid ct expectation l3proto '%s'.", tmp); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + obj->ct_expect.l3proto = l3proto; + if (!json_unpack(root, "{s:s}", "protocol", &tmp)) { +@@ -3604,8 +3601,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + obj->ct_expect.l4proto = IPPROTO_UDP; + } else { + json_error(ctx, "Invalid ct expectation protocol '%s'.", tmp); +- obj_free(obj); +- return NULL; ++ goto err_free_obj; + } + } + if (!json_unpack(root, "{s:i}", "dport", &i)) +@@ -3619,10 +3615,9 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + obj->type = NFT_OBJECT_LIMIT; + if (json_unpack_err(ctx, root, "{s:I, s:s}", + "rate", &obj->limit.rate, +- "per", &tmp)) { +- obj_free(obj); +- return NULL; +- } ++ "per", &tmp)) ++ goto err_free_obj; ++ + json_unpack(root, "{s:s}", "rate_unit", &rate_unit); + json_unpack(root, "{s:b}", "inv", &inv); + json_unpack(root, "{s:I}", "burst", &obj->limit.burst); +@@ -3643,20 +3638,18 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + case CMD_OBJ_SYNPROXY: + obj->type = NFT_OBJECT_SYNPROXY; + if (json_unpack_err(ctx, root, "{s:i, s:i}", +- "mss", &i, "wscale", &j)) { +- obj_free(obj); +- return NULL; +- } ++ "mss", &i, "wscale", &j)) ++ goto err_free_obj; ++ + obj->synproxy.mss = i; + obj->synproxy.wscale = j; + obj->synproxy.flags |= NF_SYNPROXY_OPT_MSS; + obj->synproxy.flags |= NF_SYNPROXY_OPT_WSCALE; + if (!json_unpack(root, "{s:o}", "flags", &jflags)) { + flags = json_parse_synproxy_flags(ctx, jflags); +- if (flags < 0) { +- obj_free(obj); +- return NULL; +- } ++ if (flags < 0) ++ goto err_free_obj; ++ + obj->synproxy.flags |= flags; + } + break; +@@ -3668,6 +3661,11 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx, + json_object_del(root, "handle"); + + return cmd_alloc(op, cmd_obj, &h, int_loc, obj); ++ ++err_free_obj: ++ obj_free(obj); ++ handle_free(&h); ++ return NULL; + } + + static struct cmd *json_parse_cmd_add(struct json_ctx *ctx, +@@ -3781,8 +3779,7 @@ static struct cmd *json_parse_cmd_replace(struct json_ctx *ctx, + if (!json_is_object(value)) { + json_error(ctx, "Unexpected expr array element of type %s, expected object.", + json_typename(value)); +- rule_free(rule); +- return NULL; ++ goto err_free_replace; + } + + stmt = json_parse_stmt(ctx, value); +@@ -3790,8 +3787,7 @@ static struct cmd *json_parse_cmd_replace(struct json_ctx *ctx, + if (!stmt) { + json_error(ctx, "Parsing expr array at index %zd failed.", + index); +- rule_free(rule); +- return NULL; ++ goto err_free_replace; + } + + rule_stmt_append(rule, stmt); +@@ -3801,6 +3797,11 @@ static struct cmd *json_parse_cmd_replace(struct json_ctx *ctx, + json_object_del(root, "handle"); + + return cmd_alloc(op, CMD_OBJ_RULE, &h, int_loc, rule); ++ ++err_free_replace: ++ rule_free(rule); ++ handle_free(&h); ++ return NULL; + } + + static struct cmd *json_parse_cmd_list_multiple(struct json_ctx *ctx, +-- +2.43.0 + diff --git a/backport-fix-several-expression-memleaks-from-error-path.patch b/backport-fix-several-expression-memleaks-from-error-path.patch new file mode 100644 index 0000000..ac07518 --- /dev/null +++ b/backport-fix-several-expression-memleaks-from-error-path.patch @@ -0,0 +1,41 @@ +From bae7b4d283826efbeb28c21aecd7b355e86da170 Mon Sep 17 00:00:00 2001 +From: "Sebastian Walz (sivizius)" +Date: Mon, 19 Aug 2024 20:11:44 +0200 +Subject: [PATCH] parser_json: fix several expression memleaks from error path + +Fixes: 586ad210368b ("libnftables: Implement JSON parser") +Signed-off-by: Sebastian Walz (sivizius) +Signed-off-by: Pablo Neira Ayuso +--- + src/parser_json.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/parser_json.c b/src/parser_json.c +index fc20fe29..8ca44efb 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -1308,6 +1308,7 @@ static struct expr *json_parse_range_expr(struct json_ctx *ctx, + expr_high = json_parse_primary_expr(ctx, high); + if (!expr_high) { + json_error(ctx, "Invalid high value in range expression."); ++ expr_free(expr_low); + return NULL; + } + return range_expr_alloc(int_loc, expr_low, expr_high); +@@ -1889,6 +1890,8 @@ static struct stmt *json_parse_mangle_stmt(struct json_ctx *ctx, + return stmt; + default: + json_error(ctx, "Invalid mangle statement key expression type."); ++ expr_free(key); ++ expr_free(value); + return NULL; + } + } +@@ -2888,6 +2891,7 @@ static struct stmt *json_parse_optstrip_stmt(struct json_ctx *ctx, + expr->etype != EXPR_EXTHDR || + expr->exthdr.op != NFT_EXTHDR_OP_TCPOPT) { + json_error(ctx, "Illegal TCP optstrip argument"); ++ expr_free(expr); + return NULL; + } + diff --git a/nftables.spec b/nftables.spec index b3561d4..05d7823 100644 --- a/nftables.spec +++ b/nftables.spec @@ -1,6 +1,6 @@ Name: nftables Version: 1.0.8 -Release: 5 +Release: 6 Epoch: 1 Summary: A subsystem of the Linux kernel processing network data License: GPLv2 @@ -64,6 +64,13 @@ Patch0051: backport-rule-fix-ASAN-errors-in-chain-priority-to-textual-names Patch0052: backport-tests-shell-add-regression-test-for-double-free-crash-bug.patch Patch0053: backport-evaluate-handle-invalid-mapping-expressions-in-stateful-object-statements-gracefully.patch Patch0054: backport-evaluate-Fix-incorrect-checking-the-base-variable-in-case-of-IPV6.patch +Patch0055: backport-Zero-ctx-vars-after-freeing-it.patch +Patch0056: backport-catch-wrong-reset-payload.patch +Patch0057: backport-fix-several-expression-memleaks-from-error-path.patch +Patch0058: backport-deal-appropriately-with-multidevice-in-chain.patch +Patch0059: backport-fix-handle-memleak-from-error-path.patch +Patch0060: backport-fix-crash-in-json_parse_set_stmt_list.patch + BuildRequires: gcc flex bison libmnl-devel gmp-devel readline-devel libnftnl-devel docbook2X systemd BuildRequires: iptables-devel jansson-devel python3-devel @@ -163,6 +170,18 @@ echo "%{_libdir}" > %{buildroot}/etc/ld.so.conf.d/%{name}-%{_arch}.conf %{python3_sitelib}/nftables/ %changelog +* Tue Dec 10 2024 andy - 1:1.0.8-6 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:backport upstream patches + backport-Zero-ctx-vars-after-freeing-it.patch + backport-catch-wrong-reset-payload.patch + backport-fix-several-expression-memleaks-from-error-path.patch + backport-deal-appropriately-with-multidevice-in-chain.patch + backport-fix-handle-memleak-from-error-path.patch + backport-fix-crash-in-json_parse_set_stmt_list.patch + * Wed Sep 25 2024 gaihuiying - 1:1.0.8-5 - Type:bugfix - CVE:NA -- Gitee