diff --git a/backport-libnftables-Zero-ctx-vars-after-freeing-it.patch b/backport-libnftables-Zero-ctx-vars-after-freeing-it.patch new file mode 100644 index 0000000000000000000000000000000000000000..43a135a64423f9eb733cadc14944f372d2a6eeeb --- /dev/null +++ b/backport-libnftables-Zero-ctx-vars-after-freeing-it.patch @@ -0,0 +1,34 @@ +From d361be1f8734461e27117f6c569acf2189fcf81e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 3 Sep 2024 17:43:19 +0200 +Subject: 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 + +Conflict:change context from free to xfree +Reference:https://git.netfilter.org/nftables/commit/?id=d361be1f8734461e27117f6c569acf2189fcf81e +--- + src/libnftables.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/libnftables.c b/src/libnftables.c +index 7fc81515..2ae21501 100644 +--- a/src/libnftables.c ++++ b/src/libnftables.c +@@ -160,6 +160,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); +-- +cgit v1.2.3 diff --git a/backport-parser_json-fix-handle-memleak-from-error-path.patch b/backport-parser_json-fix-handle-memleak-from-error-path.patch new file mode 100644 index 0000000000000000000000000000000000000000..4e7946dabf06aede6d55d35c89c6aeec3046a6f8 --- /dev/null +++ b/backport-parser_json-fix-handle-memleak-from-error-path.patch @@ -0,0 +1,264 @@ +From 47e18c0eba51a538e1110322d1a9248b0501d7c8 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Mon, 19 Aug 2024 21:34:49 +0200 +Subject: 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 + +Conflict:change context and delete a part code in json_parse_cmd_add_chain +Reference:https://git.netfilter.org/nftables/commit/?id=47e18c0eba51a538e1110322d1a9248b0501d7c8 +--- + 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 8ca44efb..d18188d8 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -3168,8 +3168,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; + } + + if (!json_unpack(root, "{s:s}", "dev", &name)) { +@@ -3187,8 +3185,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; + } + } + +@@ -3197,6 +3194,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, +@@ -3236,6 +3238,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; + } + +@@ -3255,16 +3258,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); +@@ -3274,6 +3275,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) +@@ -3654,8 +3660,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; +@@ -3671,8 +3676,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)) { +@@ -3682,15 +3686,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; +@@ -3704,23 +3706,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; +@@ -3728,8 +3726,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)) { +@@ -3739,8 +3736,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)) +@@ -3754,10 +3750,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); +@@ -3778,20 +3773,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; +@@ -3803,6 +3796,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, +@@ -3917,8 +3915,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); +@@ -3926,8 +3923,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); +@@ -3937,6 +3933,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, +-- +cgit v1.2.3 diff --git a/backport-parser_json-fix-several-expression-memleaks-from-error-path.patch b/backport-parser_json-fix-several-expression-memleaks-from-error-path.patch new file mode 100644 index 0000000000000000000000000000000000000000..903963b0b3550526cfb3268493569105c80284a4 --- /dev/null +++ b/backport-parser_json-fix-several-expression-memleaks-from-error-path.patch @@ -0,0 +1,38 @@ +From bae7b4d283826efbeb28c21aecd7b355e86da170 Mon Sep 17 00:00:00 2001 +From: "Sebastian Walz (sivizius)" +Date: Mon, 19 Aug 2024 20:11:44 +0200 +Subject: 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 + +Conflict:delete change about json_parse_optstrip_stmt +Reference:https://git.netfilter.org/nftables/commit/?id=bae7b4d283826efbeb28c21aecd7b355e86da170 +--- + 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; + } + } +-- +cgit v1.2.3 diff --git a/backport-parser_json-release-buffer-returned-by-json_dumps.patch b/backport-parser_json-release-buffer-returned-by-json_dumps.patch new file mode 100644 index 0000000000000000000000000000000000000000..dcc33a70850e0b1bffcd8de772acaa34a6cbe4ff --- /dev/null +++ b/backport-parser_json-release-buffer-returned-by-json_dumps.patch @@ -0,0 +1,43 @@ +From 46700fbdbbbaab0d7db716fce3a438334c58ac9e Mon Sep 17 00:00:00 2001 +From: "Sebastian Walz (sivizius)" +Date: Mon, 19 Aug 2024 19:58:14 +0200 +Subject: parser_json: release buffer returned by json_dumps + +The signature of `json_dumps` is: + +`char *json_dumps(const json_t *json, size_t flags)`: + +It will return a pointer to an owned string, the caller must free it. +However, `json_error` just borrows the string to format it as `%s`, but +after printing the formatted error message, the pointer to the string is +lost and thus never freed. + +Fixes: 586ad210368b ("libnftables: Implement JSON parser") +Signed-off-by: Sebastian Walz (sivizius) +Signed-off-by: Pablo Neira Ayuso + +Conflict:delete change about json_parse_cmd_add_set;change free_const to xfree +Reference:https://git.netfilter.org/nftables/commit/?id=46700fbdbbbaab0d7db716fce3a438334c58ac9e +--- + src/parser_json.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index 4912d360..fc20fe29 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -181,8 +181,11 @@ static int json_unpack_stmt(struct json_ctx *ctx, json_t *root, + assert(value); + + if (json_object_size(root) != 1) { ++ const char *dump = json_dumps(root, 0); ++ + json_error(ctx, "Malformed object (too many properties): '%s'.", +- json_dumps(root, 0)); ++ dump); ++ xfree(dump); + return 1; + } + +-- +cgit v1.2.3 diff --git a/nftables.spec b/nftables.spec index d9ccde78a3568a1c4e51d1e7a8f1f3601782224d..8e5cbf32d66ee315984e3d2ddfc3def3598e766c 100644 --- a/nftables.spec +++ b/nftables.spec @@ -1,6 +1,6 @@ Name: nftables Version: 1.0.0 -Release: 13 +Release: 14 Epoch: 1 Summary: A subsystem of the Linux kernel processing network data License: GPLv2 @@ -99,6 +99,11 @@ Patch80: backport-ct-timeout-fix-list-object-x-vs-list-objects-in-table-c Patch81: backport-ct-expectation-fix-list-object-x-vs-list-objects-in-table-confusion.patch Patch82: backport-tests-shell-connect-chains-to-hook-point.patch +Patch83: backport-parser_json-release-buffer-returned-by-json_dumps.patch +Patch84: backport-parser_json-fix-handle-memleak-from-error-path.patch +Patch85: backport-parser_json-fix-several-expression-memleaks-from-error-path.patch +Patch86: backport-libnftables-Zero-ctx-vars-after-freeing-it.patch + BuildRequires: gcc flex bison libmnl-devel gmp-devel readline-devel libnftnl-devel docbook2X systemd BuildRequires: iptables-devel jansson-devel python3-devel BuildRequires: chrpath @@ -197,6 +202,16 @@ echo "%{_libdir}" > %{buildroot}/etc/ld.so.conf.d/%{name}-%{_arch}.conf %{python3_sitelib}/nftables/ %changelog +* Wed Dec 11 2024 gaihuiying - 1:1.0.0-14 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:backport upstream patches + parser_json: release buffer returned by json_dumps + parser_json: fix handle memleak from error path + parser_json: fix several expression memleaks from error path + libnftables: Zero ctx->vars after freeing it + * Tue Dec 10 2024 gaihuiying - 1:1.0.0-13 - Type:bugfix - CVE:NA