From 8c13773ff044023cc1395d13e04428ada6157355 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 28 Jan 2025 00:16:16 +0000 Subject: [PATCH] import UBI nftables-1.0.4-7.el8_10 --- ...les-with-compat-expressions-in-rules.patch | 106 ++++++ ...-libxtables-access-until-translation.patch | 348 ++++++++++++++++++ SOURCES/0037-xt-Purify-enum-nft_xt_type.patch | 54 +++ ...nsupported-compat-expression-dumping.patch | 283 ++++++++++++++ ...to-generic-printing-from-translation.patch | 92 +++++ ...printing-for-extensions-matching-key.patch | 71 ++++ ...-un-break-rule-insert-with-intervals.patch | 66 ++++ .../0042-xt-Fix-translation-error-path.patch | 70 ++++ SPECS/nftables.spec | 24 +- 9 files changed, 1113 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0035-Warn-for-tables-with-compat-expressions-in-rules.patch create mode 100644 SOURCES/0036-xt-Delay-libxtables-access-until-translation.patch create mode 100644 SOURCES/0037-xt-Purify-enum-nft_xt_type.patch create mode 100644 SOURCES/0038-xt-Rewrite-unsupported-compat-expression-dumping.patch create mode 100644 SOURCES/0039-xt-Fall-back-to-generic-printing-from-translation.patch create mode 100644 SOURCES/0040-xt-Fix-fallback-printing-for-extensions-matching-key.patch create mode 100644 SOURCES/0041-evaluate-un-break-rule-insert-with-intervals.patch create mode 100644 SOURCES/0042-xt-Fix-translation-error-path.patch diff --git a/SOURCES/0035-Warn-for-tables-with-compat-expressions-in-rules.patch b/SOURCES/0035-Warn-for-tables-with-compat-expressions-in-rules.patch new file mode 100644 index 0000000..f09e341 --- /dev/null +++ b/SOURCES/0035-Warn-for-tables-with-compat-expressions-in-rules.patch @@ -0,0 +1,106 @@ +From 87b57721997aaa9f3938d2f700e13879b5cb9f72 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 14 Aug 2024 16:20:37 +0200 +Subject: [PATCH] Warn for tables with compat expressions in rules + +JIRA: https://issues.redhat.com/browse/RHEL-5806 +Upstream Status: nftables commit c327e9331e50d7b4d6cfd0a82fb38bec73703bfb + +commit c327e9331e50d7b4d6cfd0a82fb38bec73703bfb +Author: Phil Sutter +Date: Tue Oct 11 18:46:55 2022 +0200 + + Warn for tables with compat expressions in rules + + While being able to "look inside" compat expressions using nft is a nice + feature, it is also (yet another) pitfall for unaware users, deceiving + them into assuming interchangeability (or at least compatibility) + between iptables-nft and nft. + + In reality, which involves 'nft list ruleset | nft -f -', any correctly + translated compat expressions will turn into native nftables ones not + understood by (the version of) iptables-nft which created them in the + first place. Other compat expressions will vanish, potentially + compromising the firewall ruleset. + + Emit a warning (as comment) to give users a chance to stop and + reconsider before shooting their own foot. + + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + include/rule.h | 1 + + src/rule.c | 16 +++++++++++++--- + src/xt.c | 2 ++ + 3 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/include/rule.h b/include/rule.h +index 9081225..c77146a 100644 +--- a/include/rule.h ++++ b/include/rule.h +@@ -169,6 +169,7 @@ struct table { + unsigned int refcnt; + uint32_t owner; + const char *comment; ++ bool has_xt_stmts; + }; + + extern struct table *table_alloc(void); +diff --git a/src/rule.c b/src/rule.c +index 3b60cca..2fe29b1 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -1227,6 +1227,11 @@ static void table_print(const struct table *table, struct output_ctx *octx) + const char *delim = ""; + const char *family = family2str(table->handle.family); + ++ if (table->has_xt_stmts) ++ fprintf(octx->error_fp, ++ "# Warning: table %s %s is managed by iptables-nft, do not touch!\n", ++ family, table->handle.table.name); ++ + nft_print(octx, "table %s %s {", family, table->handle.table.name); + if (nft_output_handle(octx) || table->flags & TABLE_F_OWNER) + nft_print(octx, " #"); +@@ -2373,9 +2378,14 @@ static int do_list_tables(struct netlink_ctx *ctx, struct cmd *cmd) + static void table_print_declaration(struct table *table, + struct output_ctx *octx) + { +- nft_print(octx, "table %s %s {\n", +- family2str(table->handle.family), +- table->handle.table.name); ++ const char *family = family2str(table->handle.family); ++ ++ if (table->has_xt_stmts) ++ fprintf(octx->error_fp, ++ "# Warning: table %s %s is managed by iptables-nft, do not touch!\n", ++ family, table->handle.table.name); ++ ++ nft_print(octx, "table %s %s {\n", family, table->handle.table.name); + } + + static int do_list_chain(struct netlink_ctx *ctx, struct cmd *cmd, +diff --git a/src/xt.c b/src/xt.c +index 789de99..a541735 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -238,6 +238,7 @@ void netlink_parse_match(struct netlink_parse_ctx *ctx, + stmt->xt.name = strdup(name); + stmt->xt.type = NFT_XT_MATCH; + #endif ++ ctx->table->has_xt_stmts = true; + rule_stmt_append(ctx->rule, stmt); + } + +@@ -283,6 +284,7 @@ void netlink_parse_target(struct netlink_parse_ctx *ctx, + stmt->xt.name = strdup(name); + stmt->xt.type = NFT_XT_TARGET; + #endif ++ ctx->table->has_xt_stmts = true; + rule_stmt_append(ctx->rule, stmt); + } + +-- +2.45.0 + diff --git a/SOURCES/0036-xt-Delay-libxtables-access-until-translation.patch b/SOURCES/0036-xt-Delay-libxtables-access-until-translation.patch new file mode 100644 index 0000000..d80e80c --- /dev/null +++ b/SOURCES/0036-xt-Delay-libxtables-access-until-translation.patch @@ -0,0 +1,348 @@ +From 2664d616defd4f63edba2cabe7966d092ea6569f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 14 Aug 2024 16:20:37 +0200 +Subject: [PATCH] xt: Delay libxtables access until translation + +JIRA: https://issues.redhat.com/browse/RHEL-5806 +Upstream Status: nftables commit 5c30feeee5cfee74840444b63329fa5a13b471d2 + +commit 5c30feeee5cfee74840444b63329fa5a13b471d2 +Author: Phil Sutter +Date: Thu Nov 10 18:44:43 2022 +0100 + + xt: Delay libxtables access until translation + + There is no point in spending efforts setting up the xt match/target + when it is not printed afterwards. So just store the statement data from + libnftnl in struct xt_stmt and perform the extension lookup from + xt_stmt_xlate() instead. + + This means some data structures are only temporarily allocated for the + sake of passing to libxtables callbacks, no need to drag them around. + Also no need to clone the looked up extension, it is needed only to call + the functions it provides. + + While being at it, select numeric output in xt_xlate_*_params - + otherwise there will be reverse DNS lookups which should not happen by + default. + + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + include/statement.h | 9 +-- + src/xt.c | 192 ++++++++++++++++++-------------------------- + 2 files changed, 80 insertions(+), 121 deletions(-) + +diff --git a/include/statement.h b/include/statement.h +index 2a2d300..8651fc7 100644 +--- a/include/statement.h ++++ b/include/statement.h +@@ -264,12 +264,11 @@ struct xtables_target; + struct xt_stmt { + const char *name; + enum nft_xt_type type; ++ uint32_t rev; ++ uint32_t family; ++ size_t infolen; ++ void *info; + uint32_t proto; +- union { +- struct xtables_match *match; +- struct xtables_target *target; +- }; +- void *entry; + }; + + extern struct stmt *xt_stmt_alloc(const struct location *loc); +diff --git a/src/xt.c b/src/xt.c +index a541735..7880fa1 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -28,51 +28,94 @@ + + #ifdef HAVE_LIBXTABLES + #include ++ ++static void *xt_entry_alloc(const struct xt_stmt *xt, uint32_t af); + #endif + + void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + { + #ifdef HAVE_LIBXTABLES + struct xt_xlate *xl = xt_xlate_alloc(10240); ++ struct xtables_target *tg; ++ struct xt_entry_target *t; ++ struct xtables_match *mt; ++ struct xt_entry_match *m; ++ size_t size; ++ void *entry; ++ ++ xtables_set_nfproto(stmt->xt.family); ++ entry = xt_entry_alloc(&stmt->xt, stmt->xt.family); + + switch (stmt->xt.type) { + case NFT_XT_MATCH: +- if (stmt->xt.match->xlate) { ++ mt = xtables_find_match(stmt->xt.name, XTF_TRY_LOAD, NULL); ++ if (!mt) { ++ fprintf(stderr, "XT match %s not found\n", ++ stmt->xt.name); ++ return; ++ } ++ size = XT_ALIGN(sizeof(*m)) + stmt->xt.infolen; ++ ++ m = xzalloc(size); ++ memcpy(&m->data, stmt->xt.info, stmt->xt.infolen); ++ ++ m->u.match_size = size; ++ m->u.user.revision = stmt->xt.rev; ++ ++ if (mt->xlate) { + struct xt_xlate_mt_params params = { +- .ip = stmt->xt.entry, +- .match = stmt->xt.match->m, +- .numeric = 0, ++ .ip = entry, ++ .match = m, ++ .numeric = 1, + }; + +- stmt->xt.match->xlate(xl, ¶ms); ++ mt->xlate(xl, ¶ms); + nft_print(octx, "%s", xt_xlate_get(xl)); +- } else if (stmt->xt.match->print) { ++ } else if (mt->print) { + printf("#"); +- stmt->xt.match->print(&stmt->xt.entry, +- stmt->xt.match->m, 0); ++ mt->print(&entry, m, 0); + } ++ xfree(m); + break; + case NFT_XT_WATCHER: + case NFT_XT_TARGET: +- if (stmt->xt.target->xlate) { ++ tg = xtables_find_target(stmt->xt.name, XTF_TRY_LOAD); ++ if (!tg) { ++ fprintf(stderr, "XT target %s not found\n", ++ stmt->xt.name); ++ return; ++ } ++ size = XT_ALIGN(sizeof(*t)) + stmt->xt.infolen; ++ ++ t = xzalloc(size); ++ memcpy(&t->data, stmt->xt.info, stmt->xt.infolen); ++ ++ t->u.target_size = size; ++ t->u.user.revision = stmt->xt.rev; ++ ++ strcpy(t->u.user.name, tg->name); ++ ++ if (tg->xlate) { + struct xt_xlate_tg_params params = { +- .ip = stmt->xt.entry, +- .target = stmt->xt.target->t, +- .numeric = 0, ++ .ip = entry, ++ .target = t, ++ .numeric = 1, + }; + +- stmt->xt.target->xlate(xl, ¶ms); ++ tg->xlate(xl, ¶ms); + nft_print(octx, "%s", xt_xlate_get(xl)); +- } else if (stmt->xt.target->print) { ++ } else if (tg->print) { + printf("#"); +- stmt->xt.target->print(NULL, stmt->xt.target->t, 0); ++ tg->print(NULL, t, 0); + } ++ xfree(t); + break; + default: + break; + } + + xt_xlate_free(xl); ++ xfree(entry); + #else + nft_print(octx, "# xt_%s", stmt->xt.name); + #endif +@@ -80,33 +123,12 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + + void xt_stmt_destroy(struct stmt *stmt) + { +-#ifdef HAVE_LIBXTABLES +- switch (stmt->xt.type) { +- case NFT_XT_MATCH: +- if (!stmt->xt.match) +- break; +- if (stmt->xt.match->m) +- xfree(stmt->xt.match->m); +- xfree(stmt->xt.match); +- break; +- case NFT_XT_WATCHER: +- case NFT_XT_TARGET: +- if (!stmt->xt.target) +- break; +- if (stmt->xt.target->t) +- xfree(stmt->xt.target->t); +- xfree(stmt->xt.target); +- break; +- default: +- break; +- } +-#endif +- xfree(stmt->xt.entry); + xfree(stmt->xt.name); ++ xfree(stmt->xt.info); + } + + #ifdef HAVE_LIBXTABLES +-static void *xt_entry_alloc(struct xt_stmt *xt, uint32_t af) ++static void *xt_entry_alloc(const struct xt_stmt *xt, uint32_t af) + { + union nft_entry { + struct ipt_entry ipt; +@@ -173,24 +195,6 @@ static uint32_t xt_proto(const struct proto_ctx *pctx) + + return 0; + } +- +-static struct xtables_target *xt_target_clone(struct xtables_target *t) +-{ +- struct xtables_target *clone; +- +- clone = xzalloc(sizeof(struct xtables_target)); +- memcpy(clone, t, sizeof(struct xtables_target)); +- return clone; +-} +- +-static struct xtables_match *xt_match_clone(struct xtables_match *m) +-{ +- struct xtables_match *clone; +- +- clone = xzalloc(sizeof(struct xtables_match)); +- memcpy(clone, m, sizeof(struct xtables_match)); +- return clone; +-} + #endif + + /* +@@ -201,43 +205,22 @@ void netlink_parse_match(struct netlink_parse_ctx *ctx, + const struct location *loc, + const struct nftnl_expr *nle) + { +- struct stmt *stmt; +- const char *name; +-#ifdef HAVE_LIBXTABLES +- struct xtables_match *mt; + const char *mtinfo; +- struct xt_entry_match *m; ++ struct stmt *stmt; + uint32_t mt_len; + +- xtables_set_nfproto(ctx->table->handle.family); +- +- name = nftnl_expr_get_str(nle, NFTNL_EXPR_MT_NAME); +- +- mt = xtables_find_match(name, XTF_TRY_LOAD, NULL); +- if (!mt) { +- fprintf(stderr, "XT match %s not found\n", name); +- return; +- } + mtinfo = nftnl_expr_get(nle, NFTNL_EXPR_MT_INFO, &mt_len); + +- m = xzalloc(sizeof(struct xt_entry_match) + mt_len); +- memcpy(&m->data, mtinfo, mt_len); +- +- m->u.match_size = mt_len + XT_ALIGN(sizeof(struct xt_entry_match)); +- m->u.user.revision = nftnl_expr_get_u32(nle, NFTNL_EXPR_MT_REV); +- + stmt = xt_stmt_alloc(loc); +- stmt->xt.name = strdup(name); ++ stmt->xt.name = strdup(nftnl_expr_get_str(nle, NFTNL_EXPR_MT_NAME)); + stmt->xt.type = NFT_XT_MATCH; +- stmt->xt.match = xt_match_clone(mt); +- stmt->xt.match->m = m; +-#else +- name = nftnl_expr_get_str(nle, NFTNL_EXPR_MT_NAME); ++ stmt->xt.rev = nftnl_expr_get_u32(nle, NFTNL_EXPR_MT_REV); ++ stmt->xt.family = ctx->table->handle.family; ++ ++ stmt->xt.infolen = mt_len; ++ stmt->xt.info = xmalloc(mt_len); ++ memcpy(stmt->xt.info, mtinfo, mt_len); + +- stmt = xt_stmt_alloc(loc); +- stmt->xt.name = strdup(name); +- stmt->xt.type = NFT_XT_MATCH; +-#endif + ctx->table->has_xt_stmts = true; + rule_stmt_append(ctx->rule, stmt); + } +@@ -246,44 +229,22 @@ void netlink_parse_target(struct netlink_parse_ctx *ctx, + const struct location *loc, + const struct nftnl_expr *nle) + { +- struct stmt *stmt; +- const char *name; +-#ifdef HAVE_LIBXTABLES +- struct xtables_target *tg; + const void *tginfo; +- struct xt_entry_target *t; +- size_t size; ++ struct stmt *stmt; + uint32_t tg_len; + +- xtables_set_nfproto(ctx->table->handle.family); +- +- name = nftnl_expr_get_str(nle, NFTNL_EXPR_TG_NAME); +- tg = xtables_find_target(name, XTF_TRY_LOAD); +- if (!tg) { +- fprintf(stderr, "XT target %s not found\n", name); +- return; +- } + tginfo = nftnl_expr_get(nle, NFTNL_EXPR_TG_INFO, &tg_len); + +- size = XT_ALIGN(sizeof(struct xt_entry_target)) + tg_len; +- t = xzalloc(size); +- memcpy(&t->data, tginfo, tg_len); +- t->u.target_size = size; +- t->u.user.revision = nftnl_expr_get_u32(nle, NFTNL_EXPR_TG_REV); +- strcpy(t->u.user.name, tg->name); +- + stmt = xt_stmt_alloc(loc); +- stmt->xt.name = strdup(name); ++ stmt->xt.name = strdup(nftnl_expr_get_str(nle, NFTNL_EXPR_TG_NAME)); + stmt->xt.type = NFT_XT_TARGET; +- stmt->xt.target = xt_target_clone(tg); +- stmt->xt.target->t = t; +-#else +- name = nftnl_expr_get_str(nle, NFTNL_EXPR_TG_NAME); ++ stmt->xt.rev = nftnl_expr_get_u32(nle, NFTNL_EXPR_TG_REV); ++ stmt->xt.family = ctx->table->handle.family; ++ ++ stmt->xt.infolen = tg_len; ++ stmt->xt.info = xmalloc(tg_len); ++ memcpy(stmt->xt.info, tginfo, tg_len); + +- stmt = xt_stmt_alloc(loc); +- stmt->xt.name = strdup(name); +- stmt->xt.type = NFT_XT_TARGET; +-#endif + ctx->table->has_xt_stmts = true; + rule_stmt_append(ctx->rule, stmt); + } +@@ -311,7 +272,6 @@ void stmt_xt_postprocess(struct rule_pp_ctx *rctx, struct stmt *stmt, + stmt->xt.type = NFT_XT_WATCHER; + + stmt->xt.proto = xt_proto(&rctx->pctx); +- stmt->xt.entry = xt_entry_alloc(&stmt->xt, rctx->pctx.family); + } + + static int nft_xt_compatible_revision(const char *name, uint8_t rev, int opt) +-- +2.45.0 + diff --git a/SOURCES/0037-xt-Purify-enum-nft_xt_type.patch b/SOURCES/0037-xt-Purify-enum-nft_xt_type.patch new file mode 100644 index 0000000..31ec6eb --- /dev/null +++ b/SOURCES/0037-xt-Purify-enum-nft_xt_type.patch @@ -0,0 +1,54 @@ +From 89e01c6c9c9197193e83ec2b2adf14d1c6eb6f1f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 14 Aug 2024 16:20:37 +0200 +Subject: [PATCH] xt: Purify enum nft_xt_type + +JIRA: https://issues.redhat.com/browse/RHEL-5806 +Upstream Status: nftables commit e432477f5c013d0ca56f9fc5f9ac7cf35301b0b9 + +commit e432477f5c013d0ca56f9fc5f9ac7cf35301b0b9 +Author: Phil Sutter +Date: Thu Nov 24 16:24:05 2022 +0100 + + xt: Purify enum nft_xt_type + + Remove NFT_XT_MAX from the enum, it is not a valid xt type. + + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + include/statement.h | 2 +- + src/xt.c | 2 -- + 2 files changed, 1 insertion(+), 3 deletions(-) + +diff --git a/include/statement.h b/include/statement.h +index 8651fc7..e648fb1 100644 +--- a/include/statement.h ++++ b/include/statement.h +@@ -255,8 +255,8 @@ enum nft_xt_type { + NFT_XT_MATCH = 0, + NFT_XT_TARGET, + NFT_XT_WATCHER, +- NFT_XT_MAX + }; ++#define NFT_XT_MAX (NFT_XT_WATCHER + 1) + + struct xtables_match; + struct xtables_target; +diff --git a/src/xt.c b/src/xt.c +index 7880fa1..300416a 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -110,8 +110,6 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + } + xfree(t); + break; +- default: +- break; + } + + xt_xlate_free(xl); +-- +2.45.0 + diff --git a/SOURCES/0038-xt-Rewrite-unsupported-compat-expression-dumping.patch b/SOURCES/0038-xt-Rewrite-unsupported-compat-expression-dumping.patch new file mode 100644 index 0000000..61db4e8 --- /dev/null +++ b/SOURCES/0038-xt-Rewrite-unsupported-compat-expression-dumping.patch @@ -0,0 +1,283 @@ +From 5b2f626cb8770f485c20ae4f815763deac89a632 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 14 Aug 2024 16:20:37 +0200 +Subject: [PATCH] xt: Rewrite unsupported compat expression dumping + +JIRA: https://issues.redhat.com/browse/RHEL-5806 +Upstream Status: nftables commit 79195a8cc9e9d9cf2d17165bf07ac4cc9d55539f +Conflicts: +* One chunk manually applied, upstream moved stmt_print_json() in commit + e66f3187d891a ("json: add table map statement support"). + +commit 79195a8cc9e9d9cf2d17165bf07ac4cc9d55539f +Author: Phil Sutter +Date: Thu Nov 24 14:17:17 2022 +0100 + + xt: Rewrite unsupported compat expression dumping + + Choose a format which provides more information and is easily parseable. + Then teach parsers about it and make it explicitly reject the ruleset + giving a meaningful explanation. Also update the man pages with some + more details. + + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + doc/libnftables-json.adoc | 18 +++++++++++++++--- + doc/statements.txt | 17 +++++++++++++++++ + include/json.h | 2 ++ + include/parser.h | 1 + + src/json.c | 19 +++++++++++++------ + src/parser_bison.y | 18 ++++++++++++++++++ + src/parser_json.c | 5 +++++ + src/scanner.l | 3 +++ + src/statement.c | 1 + + src/xt.c | 8 +++++++- + 10 files changed, 82 insertions(+), 10 deletions(-) + +diff --git a/doc/libnftables-json.adoc b/doc/libnftables-json.adoc +index 9cc17ff..284ffab 100644 +--- a/doc/libnftables-json.adoc ++++ b/doc/libnftables-json.adoc +@@ -1059,10 +1059,22 @@ Assign connection tracking expectation. + + === XT + [verse] +-*{ "xt": null }* ++____ ++*{ "xt": { ++ "type":* 'TYPENAME'*, ++ "name":* 'STRING' ++*}}* ++ ++'TYPENAME' := *match* | *target* | *watcher* ++____ ++ ++This represents an xt statement from xtables compat interface. It is a ++fallback if translation is not available or not complete. ++ ++Seeing this means the ruleset (or parts of it) were created by *iptables-nft* ++and one should use that to manage it. + +-This represents an xt statement from xtables compat interface. Sadly, at this +-point, it is not possible to provide any further information about its content. ++*BEWARE:* nftables won't restore these statements. + + == EXPRESSIONS + Expressions are the building blocks of (most) statements. In their most basic +diff --git a/doc/statements.txt b/doc/statements.txt +index 6aaf806..a00bd5d 100644 +--- a/doc/statements.txt ++++ b/doc/statements.txt +@@ -778,3 +778,20 @@ ____ + # jump to different chains depending on layer 4 protocol type: + nft add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain } + ------------------------ ++ ++XT STATEMENT ++~~~~~~~~~~~~ ++This represents an xt statement from xtables compat interface. It is a ++fallback if translation is not available or not complete. ++ ++[verse] ++____ ++*xt* 'TYPE' 'NAME' ++ ++'TYPE' := *match* | *target* | *watcher* ++____ ++ ++Seeing this means the ruleset (or parts of it) were created by *iptables-nft* ++and one should use that to manage it. ++ ++*BEWARE:* nftables won't restore these statements. +diff --git a/include/json.h b/include/json.h +index b0d78eb..f691678 100644 +--- a/include/json.h ++++ b/include/json.h +@@ -92,6 +92,7 @@ json_t *connlimit_stmt_json(const struct stmt *stmt, struct output_ctx *octx); + json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx); + json_t *synproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx); + json_t *optstrip_stmt_json(const struct stmt *stmt, struct output_ctx *octx); ++json_t *xt_stmt_json(const struct stmt *stmt, struct output_ctx *octx); + + int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd); + +@@ -194,6 +195,7 @@ STMT_PRINT_STUB(connlimit) + STMT_PRINT_STUB(tproxy) + STMT_PRINT_STUB(synproxy) + STMT_PRINT_STUB(optstrip) ++STMT_PRINT_STUB(xt) + + #undef STMT_PRINT_STUB + #undef EXPR_PRINT_STUB +diff --git a/include/parser.h b/include/parser.h +index 5e5ad28..bd61b8f 100644 +--- a/include/parser.h ++++ b/include/parser.h +@@ -50,6 +50,7 @@ enum startcond_type { + PARSER_SC_TCP, + PARSER_SC_TYPE, + PARSER_SC_VLAN, ++ PARSER_SC_XT, + PARSER_SC_CMD_EXPORT, + PARSER_SC_CMD_IMPORT, + PARSER_SC_CMD_LIST, +diff --git a/src/json.c b/src/json.c +index a525fd1..622fe08 100644 +--- a/src/json.c ++++ b/src/json.c +@@ -173,12 +173,6 @@ static json_t *stmt_print_json(const struct stmt *stmt, struct output_ctx *octx) + char buf[1024]; + FILE *fp; + +- /* XXX: Can't be supported at this point: +- * xt_stmt_xlate() ignores output_fp. +- */ +- if (stmt->ops->type == STMT_XT) +- return json_pack("{s:n}", "xt"); +- + if (stmt->ops->json) + return stmt->ops->json(stmt, octx); + +@@ -1584,6 +1578,19 @@ json_t *optstrip_stmt_json(const struct stmt *stmt, struct output_ctx *octx) + expr_print_json(stmt->optstrip.expr, octx)); + } + ++json_t *xt_stmt_json(const struct stmt *stmt, struct output_ctx *octx) ++{ ++ static const char *xt_typename[NFT_XT_MAX] = { ++ [NFT_XT_MATCH] = "match", ++ [NFT_XT_TARGET] = "target", ++ [NFT_XT_WATCHER] = "watcher", ++ }; ++ ++ return json_pack("{s:{s:s, s:s}}", "xt", ++ "type", xt_typename[stmt->xt.type], ++ "name", stmt->xt.name); ++} ++ + static json_t *table_print_json_full(struct netlink_ctx *ctx, + struct table *table) + { +diff --git a/src/parser_bison.y b/src/parser_bison.y +index b882f3b..a9d16f8 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -615,6 +615,8 @@ int nft_lex(void *, void *, void *); + %token IN "in" + %token OUT "out" + ++%token XT "xt" ++ + %type limit_rate_pkts + %type limit_rate_bytes + +@@ -889,6 +891,9 @@ int nft_lex(void *, void *, void *); + %type optstrip_stmt + %destructor { stmt_free($$); } optstrip_stmt + ++%type xt_stmt ++%destructor { stmt_free($$); } xt_stmt ++ + %type boolean_expr + %destructor { expr_free($$); } boolean_expr + %type boolean_keys +@@ -981,6 +986,7 @@ close_scope_udplite : { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_UDPL + + close_scope_log : { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_LOG); } + close_scope_synproxy : { scanner_pop_start_cond(nft->scanner, PARSER_SC_STMT_SYNPROXY); } ++close_scope_xt : { scanner_pop_start_cond(nft->scanner, PARSER_SC_XT); } + + common_block : INCLUDE QUOTED_STRING stmt_separator + { +@@ -2861,6 +2867,18 @@ stmt : verdict_stmt + | synproxy_stmt close_scope_synproxy + | chain_stmt + | optstrip_stmt ++ | xt_stmt close_scope_xt ++ ; ++ ++xt_stmt : XT STRING STRING ++ { ++ $$ = NULL; ++ xfree($2); ++ xfree($3); ++ erec_queue(error(&@$, "unsupported xtables compat expression, use iptables-nft with this ruleset"), ++ state->msgs); ++ YYERROR; ++ } + ; + + chain_stmt_type : JUMP { $$ = NFT_JUMP; } +diff --git a/src/parser_json.c b/src/parser_json.c +index fb40100..1699a44 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -2716,6 +2716,11 @@ static struct stmt *json_parse_stmt(struct json_ctx *ctx, json_t *root) + return verdict_stmt_alloc(int_loc, expr); + } + ++ if (!strcmp(type, "xt")) { ++ json_error(ctx, "unsupported xtables compat expression, use iptables-nft with this ruleset"); ++ return NULL; ++ } ++ + for (i = 0; i < array_size(stmt_parser_tbl); i++) { + if (!strcmp(type, stmt_parser_tbl[i].key)) + return stmt_parser_tbl[i].cb(ctx, stmt_parser_tbl[i].key, tmp); +diff --git a/src/scanner.l b/src/scanner.l +index ed7256b..64d21df 100644 +--- a/src/scanner.l ++++ b/src/scanner.l +@@ -215,6 +215,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) + %s SCANSTATE_TCP + %s SCANSTATE_TYPE + %s SCANSTATE_VLAN ++%s SCANSTATE_XT + %s SCANSTATE_CMD_EXPORT + %s SCANSTATE_CMD_IMPORT + %s SCANSTATE_CMD_LIST +@@ -803,6 +804,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) + + "secmark" { scanner_push_start_cond(yyscanner, SCANSTATE_SECMARK); return SECMARK; } + ++"xt" { scanner_push_start_cond(yyscanner, SCANSTATE_XT); return XT; } ++ + {addrstring} { + yylval->string = xstrdup(yytext); + return STRING; +diff --git a/src/statement.c b/src/statement.c +index 30caf9c..0448c85 100644 +--- a/src/statement.c ++++ b/src/statement.c +@@ -997,6 +997,7 @@ static const struct stmt_ops xt_stmt_ops = { + .name = "xt", + .print = xt_stmt_print, + .destroy = xt_stmt_destroy, ++ .json = xt_stmt_json, + }; + + struct stmt *xt_stmt_alloc(const struct location *loc) +diff --git a/src/xt.c b/src/xt.c +index 300416a..12b52aa 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -115,7 +115,13 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + xt_xlate_free(xl); + xfree(entry); + #else +- nft_print(octx, "# xt_%s", stmt->xt.name); ++ static const char *typename[NFT_XT_MAX] = { ++ [NFT_XT_MATCH] = "match", ++ [NFT_XT_TARGET] = "target", ++ [NFT_XT_WATCHER] = "watcher", ++ }; ++ ++ nft_print(octx, "xt %s %s", typename[stmt->xt.type], stmt->xt.name); + #endif + } + +-- +2.45.0 + diff --git a/SOURCES/0039-xt-Fall-back-to-generic-printing-from-translation.patch b/SOURCES/0039-xt-Fall-back-to-generic-printing-from-translation.patch new file mode 100644 index 0000000..ab0c493 --- /dev/null +++ b/SOURCES/0039-xt-Fall-back-to-generic-printing-from-translation.patch @@ -0,0 +1,92 @@ +From e0a2f227d1d3cfb60561144318e81f74a7516d38 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 14 Aug 2024 16:21:18 +0200 +Subject: [PATCH] xt: Fall back to generic printing from translation + +JIRA: https://issues.redhat.com/browse/RHEL-5806 +Upstream Status: nftables commit e41c53ca5b043e8cee493bf4a7f78195827279d2 + +commit e41c53ca5b043e8cee493bf4a7f78195827279d2 +Author: Phil Sutter +Date: Thu Nov 24 16:16:41 2022 +0100 + + xt: Fall back to generic printing from translation + + If translation is not available or fails, print the generic format + instead of calling the print callback (which does not respect + output_fp) or silently failing. + + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + src/xt.c | 31 +++++++++++++------------------ + 1 file changed, 13 insertions(+), 18 deletions(-) + +diff --git a/src/xt.c b/src/xt.c +index 12b52aa..b75c94e 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -34,6 +34,12 @@ static void *xt_entry_alloc(const struct xt_stmt *xt, uint32_t af); + + void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + { ++ static const char *typename[NFT_XT_MAX] = { ++ [NFT_XT_MATCH] = "match", ++ [NFT_XT_TARGET] = "target", ++ [NFT_XT_WATCHER] = "watcher", ++ }; ++ int rc = 0; + #ifdef HAVE_LIBXTABLES + struct xt_xlate *xl = xt_xlate_alloc(10240); + struct xtables_target *tg; +@@ -69,11 +75,7 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + .numeric = 1, + }; + +- mt->xlate(xl, ¶ms); +- nft_print(octx, "%s", xt_xlate_get(xl)); +- } else if (mt->print) { +- printf("#"); +- mt->print(&entry, m, 0); ++ rc = mt->xlate(xl, ¶ms); + } + xfree(m); + break; +@@ -102,27 +104,20 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + .numeric = 1, + }; + +- tg->xlate(xl, ¶ms); +- nft_print(octx, "%s", xt_xlate_get(xl)); +- } else if (tg->print) { +- printf("#"); +- tg->print(NULL, t, 0); ++ rc = tg->xlate(xl, ¶ms); + } + xfree(t); + break; + } + ++ if (rc == 1) ++ nft_print(octx, "%s", xt_xlate_get(xl)); + xt_xlate_free(xl); + xfree(entry); +-#else +- static const char *typename[NFT_XT_MAX] = { +- [NFT_XT_MATCH] = "match", +- [NFT_XT_TARGET] = "target", +- [NFT_XT_WATCHER] = "watcher", +- }; +- +- nft_print(octx, "xt %s %s", typename[stmt->xt.type], stmt->xt.name); + #endif ++ if (!rc) ++ nft_print(octx, "xt %s %s", ++ typename[stmt->xt.type], stmt->xt.name); + } + + void xt_stmt_destroy(struct stmt *stmt) +-- +2.45.0 + diff --git a/SOURCES/0040-xt-Fix-fallback-printing-for-extensions-matching-key.patch b/SOURCES/0040-xt-Fix-fallback-printing-for-extensions-matching-key.patch new file mode 100644 index 0000000..961b423 --- /dev/null +++ b/SOURCES/0040-xt-Fix-fallback-printing-for-extensions-matching-key.patch @@ -0,0 +1,71 @@ +From eafc3f2d2dbc367b022a51a9208cc6d861b9e10d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 14 Aug 2024 16:21:19 +0200 +Subject: [PATCH] xt: Fix fallback printing for extensions matching keywords + +JIRA: https://issues.redhat.com/browse/RHEL-5806 +Upstream Status: nftables commit aef5330fe7827f760b70d5d27010445c3adb3d3c + +commit aef5330fe7827f760b70d5d27010445c3adb3d3c +Author: Phil Sutter +Date: Thu Mar 9 14:31:31 2023 +0100 + + xt: Fix fallback printing for extensions matching keywords + + Yet another Bison workaround: Instead of the fancy error message, an + incomprehensible syntax error is emitted: + + | # iptables-nft -A FORWARD -p tcp -m osf --genre linux + | # nft list ruleset | nft -f - + | # Warning: table ip filter is managed by iptables-nft, do not touch! + | /dev/stdin:4:29-31: Error: syntax error, unexpected osf, expecting string + | meta l4proto tcp xt match osf counter packets 0 bytes 0 + | ^^^ + + Avoid this by quoting the extension name when printing: + + | # nft list ruleset | sudo ./src/nft -f - + | # Warning: table ip filter is managed by iptables-nft, do not touch! + | /dev/stdin:4:20-33: Error: unsupported xtables compat expression, use iptables-nft with this ruleset + | meta l4proto tcp xt match "osf" counter packets 0 bytes 0 + | ^^^^^^^^^^^^^^ + + Fixes: 79195a8cc9e9d ("xt: Rewrite unsupported compat expression dumping") + Fixes: e41c53ca5b043 ("xt: Fall back to generic printing from translation") + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + src/parser_bison.y | 2 +- + src/xt.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/parser_bison.y b/src/parser_bison.y +index a9d16f8..1ca0c25 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -2870,7 +2870,7 @@ stmt : verdict_stmt + | xt_stmt close_scope_xt + ; + +-xt_stmt : XT STRING STRING ++xt_stmt : XT STRING string + { + $$ = NULL; + xfree($2); +diff --git a/src/xt.c b/src/xt.c +index b75c94e..31cf40e 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -116,7 +116,7 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + xfree(entry); + #endif + if (!rc) +- nft_print(octx, "xt %s %s", ++ nft_print(octx, "xt %s \"%s\"", + typename[stmt->xt.type], stmt->xt.name); + } + +-- +2.45.0 + diff --git a/SOURCES/0041-evaluate-un-break-rule-insert-with-intervals.patch b/SOURCES/0041-evaluate-un-break-rule-insert-with-intervals.patch new file mode 100644 index 0000000..b49f195 --- /dev/null +++ b/SOURCES/0041-evaluate-un-break-rule-insert-with-intervals.patch @@ -0,0 +1,66 @@ +From 39c9fb961fe827a104e17a8ffa7ed63e51e3f522 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 29 Oct 2024 19:40:56 +0100 +Subject: [PATCH] evaluate: un-break rule insert with intervals + +JIRA: https://issues.redhat.com/browse/RHEL-62895 +Upstream Status: nftables commit 91626261c9dfedbd1e8ff40959b453418ebc8fb6 + +commit 91626261c9dfedbd1e8ff40959b453418ebc8fb6 +Author: Florian Westphal +Date: Tue Sep 20 15:26:07 2022 +0200 + + evaluate: un-break rule insert with intervals + + 'rule inet dscpclassify dscp_match meta l4proto { udp } th dport { 3478 } th sport { 3478-3497, 16384-16387 } goto ct_set_ef' + works with 'nft add', but not 'nft insert', the latter yields: "BUG: unhandled op 4". + + Fixes: 81e36530fcac ("src: replace interval segment tree overlap and automerge") + Signed-off-by: Florian Westphal + Acked-by: Pablo Neira Ayuso + +Signed-off-by: Phil Sutter +--- + src/evaluate.c | 1 + + tests/shell/testcases/rule_management/0003insert_0 | 4 ++++ + tests/shell/testcases/rule_management/dumps/0003insert_0.nft | 1 + + 3 files changed, 6 insertions(+) + +diff --git a/src/evaluate.c b/src/evaluate.c +index 6d0a0f5..c6d656b 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -1505,6 +1505,7 @@ static int interval_set_eval(struct eval_ctx *ctx, struct set *set, + switch (ctx->cmd->op) { + case CMD_CREATE: + case CMD_ADD: ++ case CMD_INSERT: + if (set->automerge) { + ret = set_automerge(ctx->msgs, ctx->cmd, set, init, + ctx->nft->debug_mask); +diff --git a/tests/shell/testcases/rule_management/0003insert_0 b/tests/shell/testcases/rule_management/0003insert_0 +index 329ccc2..c343d57 100755 +--- a/tests/shell/testcases/rule_management/0003insert_0 ++++ b/tests/shell/testcases/rule_management/0003insert_0 +@@ -9,3 +9,7 @@ $NFT add chain t c + $NFT insert rule t c accept + $NFT insert rule t c drop + $NFT insert rule t c masquerade ++ ++# check 'evaluate: un-break rule insert with intervals' ++ ++$NFT insert rule t c tcp sport { 3478-3497, 16384-16387 } +diff --git a/tests/shell/testcases/rule_management/dumps/0003insert_0.nft b/tests/shell/testcases/rule_management/dumps/0003insert_0.nft +index 9421f4a..b1875ab 100644 +--- a/tests/shell/testcases/rule_management/dumps/0003insert_0.nft ++++ b/tests/shell/testcases/rule_management/dumps/0003insert_0.nft +@@ -1,5 +1,6 @@ + table ip t { + chain c { ++ tcp sport { 3478-3497, 16384-16387 } + masquerade + drop + accept +-- +2.46.2 + diff --git a/SOURCES/0042-xt-Fix-translation-error-path.patch b/SOURCES/0042-xt-Fix-translation-error-path.patch new file mode 100644 index 0000000..8157f86 --- /dev/null +++ b/SOURCES/0042-xt-Fix-translation-error-path.patch @@ -0,0 +1,70 @@ +From 5e5919ad698c6edfd0c1bbbd47d97309c0cb7a83 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 29 Nov 2024 12:01:39 +0100 +Subject: [PATCH] xt: Fix translation error path + +JIRA: https://issues.redhat.com/browse/RHEL-5806 +Upstream Status: nftables commit ce3d71348ee77d2d7ffa6a825afbc7471e92bc89 + +commit ce3d71348ee77d2d7ffa6a825afbc7471e92bc89 +Author: Phil Sutter +Date: Tue Mar 28 13:46:10 2023 +0200 + + xt: Fix translation error path + + If xtables support was compiled in but the required libxtables DSO is + not found, nft prints an error message and leaks memory: + + | counter packets 0 bytes 0 XT target MASQUERADE not found + + This is not as bad as it seems, the output combines stdout and stderr. + Dropping stderr produces an incomplete ruleset listing, though. While + this seemingly inline output can't easily be avoided, fix a few things: + + * Respect octx->error_fp, libnftables might have been configured to + redirect stderr somewhere else. + * Align error message formatting with others. + * Don't return immediately, but free allocated memory and fall back to + printing the expression in "untranslated" form. + + Fixes: 5c30feeee5cfe ("xt: Delay libxtables access until translation") + Signed-off-by: Phil Sutter + +Signed-off-by: Phil Sutter +--- + src/xt.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/xt.c b/src/xt.c +index 31cf40e..6d5866d 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -56,9 +56,10 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + case NFT_XT_MATCH: + mt = xtables_find_match(stmt->xt.name, XTF_TRY_LOAD, NULL); + if (!mt) { +- fprintf(stderr, "XT match %s not found\n", ++ fprintf(octx->error_fp, ++ "# Warning: XT match %s not found\n", + stmt->xt.name); +- return; ++ break; + } + size = XT_ALIGN(sizeof(*m)) + stmt->xt.infolen; + +@@ -83,9 +84,10 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + case NFT_XT_TARGET: + tg = xtables_find_target(stmt->xt.name, XTF_TRY_LOAD); + if (!tg) { +- fprintf(stderr, "XT target %s not found\n", ++ fprintf(octx->error_fp, ++ "# Warning: XT target %s not found\n", + stmt->xt.name); +- return; ++ break; + } + size = XT_ALIGN(sizeof(*t)) + stmt->xt.infolen; + +-- +2.46.2 + diff --git a/SPECS/nftables.spec b/SPECS/nftables.spec index b988917..c4fcde2 100644 --- a/SPECS/nftables.spec +++ b/SPECS/nftables.spec @@ -1,5 +1,5 @@ %define nft_rpmversion 1.0.4 -%define nft_specrelease 4 +%define nft_specrelease 7 %define libnftnl_ver 1.2.2-1 Name: nftables @@ -55,6 +55,14 @@ Patch31: 0031-netlink_delinearize-Sanitize-concat-data-element-dec.pa Patch32: 0032-tests-monitor-Summarize-failures-per-test-case.patch Patch33: 0033-rule-check-address-family-in-set-collapse.patch Patch34: 0034-parser_bison-Fix-for-broken-compatibility-with-older.patch +Patch35: 0035-Warn-for-tables-with-compat-expressions-in-rules.patch +Patch36: 0036-xt-Delay-libxtables-access-until-translation.patch +Patch37: 0037-xt-Purify-enum-nft_xt_type.patch +Patch38: 0038-xt-Rewrite-unsupported-compat-expression-dumping.patch +Patch39: 0039-xt-Fall-back-to-generic-printing-from-translation.patch +Patch40: 0040-xt-Fix-fallback-printing-for-extensions-matching-key.patch +Patch41: 0041-evaluate-un-break-rule-insert-with-intervals.patch +Patch42: 0042-xt-Fix-translation-error-path.patch BuildRequires: autoconf BuildRequires: automake @@ -174,6 +182,20 @@ touch -r %{SOURCE2} $RPM_BUILD_ROOT/%{python3_sitelib}/nftables/nftables.py %{python3_sitelib}/nftables/ %changelog +* Fri Nov 29 2024 Phil Sutter [1.0.4-7.el8] +- xt: Fix translation error path (Phil Sutter) [RHEL-5806] + +* Tue Oct 29 2024 Phil Sutter [1.0.4-6.el8] +- evaluate: un-break rule insert with intervals (Phil Sutter) [RHEL-62895] + +* Wed Aug 14 2024 Phil Sutter [1.0.4-5.el8] +- xt: Fix fallback printing for extensions matching keywords (Phil Sutter) [RHEL-5806] +- xt: Fall back to generic printing from translation (Phil Sutter) [RHEL-5806] +- xt: Rewrite unsupported compat expression dumping (Phil Sutter) [RHEL-5806] +- xt: Purify enum nft_xt_type (Phil Sutter) [RHEL-5806] +- xt: Delay libxtables access until translation (Phil Sutter) [RHEL-5806] +- Warn for tables with compat expressions in rules (Phil Sutter) [RHEL-5806] + * Wed Nov 15 2023 Phil Sutter [1.0.4-4.el8] - parser_bison: Fix for broken compatibility with older dumps (Phil Sutter) [RHEL-2596]